X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_le_adapter%2Ftizen%2Fcaleclient.c;h=a82996040f6cf9c9b15a163ddf8bd67773dd119f;hb=bdec944c51c8e0063b6ee0890170e828ac8f2b96;hp=1666724d904f8d536ea6f6e59beb037e872238b2;hpb=0e7762704ad69d816015184a55177d17c701188b;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c index 1666724..a829960 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c @@ -30,11 +30,10 @@ #include #include -#include "camutex.h" +#include "octhread.h" #include "uarraylist.h" #include "caqueueingthread.h" #include "caadapterutils.h" -#include "cafragmentation.h" #include "cagattservice.h" #include "oic_string.h" #include "oic_malloc.h" @@ -45,6 +44,7 @@ #define TAG "OIC_CA_LE_CLIENT" #define MICROSECS_PER_SEC 1000000 +#define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC; @@ -61,7 +61,7 @@ static u_arraylist_t *g_multicastDataList = NULL; /** * Mutex to synchronize the access to Pending multicast data list. */ -static ca_mutex g_multicastDataListMutex = NULL; +static oc_mutex g_multicastDataListMutex = NULL; /** * List of devices discovered. @@ -71,17 +71,17 @@ static u_arraylist_t *g_deviceDiscoveredList = NULL; /** * Mutex to synchronize the access to discovered devices list. */ -static ca_mutex g_deviceDiscoveredListMutex = NULL; +static oc_mutex g_deviceDiscoveredListMutex = NULL; /** * Condition to start the timer for scanning. */ -static ca_cond g_startTimerCond = NULL; +static oc_cond g_startTimerCond = NULL; /** * Condition for scanning Time interval. */ -static ca_cond g_scanningTimeCond = NULL; +static oc_cond g_scanningTimeCond = NULL; /** * This contains the list of OIC services a client connect tot. @@ -91,7 +91,7 @@ static LEServerInfoList *g_LEServerList = NULL; /** * Mutex to synchronize access to BleServiceList. */ -static ca_mutex g_LEServerListMutex = NULL; +static oc_mutex g_LEServerListMutex = NULL; /** * Boolean variable to keep the state of the GATT Client. @@ -102,24 +102,39 @@ static bool g_isLEGattClientStarted = false; * Mutex to synchronize access to the requestResponse callback to be called * when the data needs to be sent from GATTClient. */ -static ca_mutex g_LEReqRespClientCbMutex = NULL; +static oc_mutex g_LEReqRespClientCbMutex = NULL; /** * Mutex to synchronize access to the requestResponse callback to be called * when the data needs to be sent from GATTClient. */ -static ca_mutex g_LEClientConnectMutex = NULL; +static oc_mutex g_LEClientConnectMutex = NULL; /** * Mutex to synchronize the calls to be done to the platform from GATTClient * interfaces from different threads. */ -static ca_mutex g_LEClientStateMutex = NULL; +static oc_mutex g_LEClientStateMutex = NULL; /** * Mutex to synchronize the task to be pushed to thread pool. */ -static ca_mutex g_LEClientThreadPoolMutex = NULL; +static oc_mutex g_LEClientThreadPoolMutex = NULL; + +/** + * Mutex to synchronize the task to write characteristic one packet after another. + */ +static oc_mutex g_threadWriteCharacteristicMutex = NULL; + +/** + * Condition for Writing characteristic. + */ +static oc_cond g_threadWriteCharacteristicCond = NULL; + +/** + * Flag to check status of write characteristic. + */ +static bool g_isSignalSetFlag = false; /** * Maintains the callback to be notified on receival of network packets from other @@ -142,29 +157,74 @@ static GMainLoop *g_eventLoop = NULL; */ static ca_thread_pool_t g_LEClientThreadPool = NULL; -bt_scan_filter_h g_scanFilter = NULL; +bool CALEIsHaveService(bt_adapter_le_device_scan_result_info_s* scanInfo, char* service_uuid) +{ + bool ret = false; + char **uuids = NULL; + int count = 0; + int result = 0; + + // For arduino servers, scan response will give the UUIDs advertised. + result = bt_adapter_le_get_scan_result_service_uuids(scanInfo, + BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, + &uuids, &count); + if (result == BT_ERROR_NONE && NULL != uuids) + { + int i; + for (i = 0; i < count; i++) + { + if (0 == strcasecmp(uuids[i], service_uuid)) + { + OIC_LOG_V(DEBUG, TAG, "Service[%s] Found in %s", + uuids[i], scanInfo->remote_address); + ret = true; + } + OICFree(uuids[i]); + } + OICFree(uuids); + } + + // For android/tizen servers, advertising packet will give the UUIDs. + result = bt_adapter_le_get_scan_result_service_uuids(scanInfo, + BT_ADAPTER_LE_PACKET_ADVERTISING, + &uuids, &count); + if (result == BT_ERROR_NONE && NULL != uuids) + { + int i; + for (i = 0; i < count; i++) + { + if (0 == strcasecmp(uuids[i], service_uuid)) + { + OIC_LOG_V(DEBUG, TAG, "Service[%s] Found in %s", + uuids[i], scanInfo->remote_address); + ret = true; + } + OICFree(uuids[i]); + } + OICFree(uuids); + } + + return ret; +} bool CALEIsDeviceDiscovered(const char * address) { - OIC_LOG(DEBUG, TAG, "IN"); if (g_deviceDiscoveredList) { - ca_mutex_lock(g_deviceDiscoveredListMutex); + oc_mutex_lock(g_deviceDiscoveredListMutex); uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList); - for (int i = 0; i < arrayLength; i++) + for (uint32_t i = 0; i < arrayLength; i++) { char *deviceAddr = u_arraylist_get(g_deviceDiscoveredList, i); if (0 == strcasecmp(deviceAddr, address)) { - OIC_LOG(DEBUG, TAG, "Device Found"); - ca_mutex_unlock(g_deviceDiscoveredListMutex); + oc_mutex_unlock(g_deviceDiscoveredListMutex); return true; } } - ca_mutex_unlock(g_deviceDiscoveredListMutex); + oc_mutex_unlock(g_deviceDiscoveredListMutex); } - OIC_LOG(DEBUG, TAG, "OUT"); return false; } @@ -172,35 +232,60 @@ void CALEGattCharacteristicChangedCb(bt_gatt_h characteristic, char *value, int valueLen, void *userData) { + (void)characteristic; + OIC_LOG(DEBUG, TAG, "IN"); OIC_LOG_V(DEBUG, TAG, "Changed characteristic value length [%d]", valueLen); - ca_mutex_lock(g_LEReqRespClientCbMutex); + oc_mutex_lock(g_LEReqRespClientCbMutex); if (NULL == g_LEClientDataReceivedCallback) { OIC_LOG(ERROR, TAG, "Request response callback is not set"); - ca_mutex_unlock(g_LEReqRespClientCbMutex); + oc_mutex_unlock(g_LEReqRespClientCbMutex); return; } uint32_t sentLength = 0; g_LEClientDataReceivedCallback(userData, (uint8_t *)value, valueLen, &sentLength); - OIC_LOG_V(DEBUG, TAG, "Sent data Length is %d", sentLength); + OIC_LOG_V(DEBUG, TAG, "Recv data Length is %d", sentLength); - ca_mutex_unlock(g_LEReqRespClientCbMutex); + oc_mutex_unlock(g_LEReqRespClientCbMutex); OIC_LOG(DEBUG, TAG, "OUT"); } void CALEGattCharacteristicWriteCb(int result, bt_gatt_h reqHandle, void *userData) { + (void)reqHandle; + (void)userData; + OIC_LOG(DEBUG, TAG, "IN "); + + if (BT_ERROR_NONE != result) + { + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1, + false, "writeChar failure"); + + OIC_LOG(ERROR, TAG, "Write failed Need Retry "); + //Need to Implement retry mechanism + } + else + { + oc_mutex_lock(g_threadWriteCharacteristicMutex); + OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal"); + g_isSignalSetFlag = true; + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, "", 0, -1, + true, "writeChar success"); + } + OIC_LOG(DEBUG, TAG, "OUT "); } -void CALEGattConnectionStateChangedCb(int result, bool connected, - const char *remoteAddress, void *userData) +void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress) { OIC_LOG(DEBUG, TAG, "IN "); @@ -213,35 +298,43 @@ void CALEGattConnectionStateChangedCb(int result, bool connected, OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed"); } // Signal the start timer. - ca_cond_signal(g_scanningTimeCond); + oc_cond_signal(g_scanningTimeCond); if (!connected) { OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress); + oc_mutex_lock(g_LEServerListMutex); + CARemoveLEServerInfoFromList(&g_LEServerList, remoteAddress); + oc_mutex_unlock(g_LEServerListMutex); } else { OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress); char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + OIC_LOG(ERROR, TAG, "addr is NULL"); + return; + } - ca_mutex_lock(g_LEClientThreadPoolMutex); + oc_mutex_lock(g_LEClientThreadPoolMutex); if (NULL == g_LEClientThreadPool) { OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); OICFree(addr); - ca_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientThreadPoolMutex); return; } ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, - addr); + addr, NULL); if (CA_STATUS_OK != ret) { OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret); OICFree(addr); } - ca_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientThreadPoolMutex); } OIC_LOG(DEBUG, TAG, "OUT"); } @@ -249,6 +342,8 @@ void CALEGattConnectionStateChangedCb(int result, bool connected, void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s *scanInfo, void *userData) { + (void)userData; + OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL_VOID(scanInfo, TAG, "scanInfo"); @@ -268,18 +363,30 @@ void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s return; } - // Stop the scan before invoking bt_gatt_connect(). - CALEGattStopDeviceScanning(); - - ca_mutex_lock(g_deviceDiscoveredListMutex); - // Add the the device Discovered list. - if (NULL == g_deviceDiscoveredList) + if (!CALEIsHaveService(scanInfo, CA_GATT_SERVICE_UUID)) { - g_deviceDiscoveredList = u_arraylist_create(); + oc_mutex_lock(g_deviceDiscoveredListMutex); + // Add the the device Discovered list. + if (NULL == g_deviceDiscoveredList) + { + g_deviceDiscoveredList = u_arraylist_create(); + } + char *deviceAddr = OICStrdup(scanInfo->remote_address); + if (NULL == deviceAddr) + { + OIC_LOG_V(ERROR, TAG, "Device address is NULL"); + oc_mutex_unlock(g_deviceDiscoveredListMutex); + return; + } + + u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr); + oc_mutex_unlock(g_deviceDiscoveredListMutex); + OIC_LOG_V(INFO, TAG, "Device[%s] is don't have service", scanInfo->remote_address); + return; } - char *deviceAddr = OICStrdup(scanInfo->remote_address); - u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr); - ca_mutex_unlock(g_deviceDiscoveredListMutex); + + // Stop the scan before invoking bt_gatt_connect(). + CALEGattStopDeviceScanning(); size_t len = strlen(scanInfo->remote_address); @@ -291,23 +398,23 @@ void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s OIC_LOG_V(DEBUG, TAG, "Trying to do Gatt connection to [%s]", addr); - ca_mutex_lock(g_LEClientThreadPoolMutex); + oc_mutex_lock(g_LEClientThreadPoolMutex); if (NULL == g_LEClientThreadPool) { OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); OICFree(addr); - ca_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientThreadPoolMutex); return; } - CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr); + CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr, NULL); if (CA_STATUS_OK != res) { OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", res); OICFree(addr); } - ca_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientThreadPoolMutex); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -315,9 +422,9 @@ void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle) { OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_lock(g_LEClientThreadPoolMutex); + oc_mutex_lock(g_LEClientThreadPoolMutex); g_LEClientThreadPool = handle; - ca_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientThreadPoolMutex); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -326,11 +433,11 @@ void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback) { OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_lock(g_LEReqRespClientCbMutex); + oc_mutex_lock(g_LEReqRespClientCbMutex); g_LEClientDataReceivedCallback = callback; - ca_mutex_unlock(g_LEReqRespClientCbMutex); + oc_mutex_unlock(g_LEReqRespClientCbMutex); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -344,104 +451,75 @@ CAResult_t CAStartLEGattClient() { OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_lock(g_LEClientThreadPoolMutex); - if (NULL == g_LEClientThreadPool) - { - OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL"); - CATerminateGattClientMutexVariables(); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - return CA_STATUS_FAILED; - } - - CAResult_t result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartLEGattClientThread, - NULL); - if (CA_STATUS_OK != result) - { - OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed"); - CATerminateGattClientMutexVariables(); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - return CA_STATUS_FAILED; - } - ca_mutex_unlock(g_LEClientThreadPoolMutex); - - OIC_LOG(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; -} - -void CAStartLEGattClientThread(void *data) -{ - OIC_LOG(DEBUG, TAG, "IN"); - - ca_mutex_lock(g_LEClientStateMutex); + oc_mutex_lock(g_LEClientStateMutex); if (true == g_isLEGattClientStarted) { OIC_LOG(ERROR, TAG, "Gatt Client is already running!!"); - ca_mutex_unlock(g_LEClientStateMutex); - return; + oc_mutex_unlock(g_LEClientStateMutex); + return CA_STATUS_FAILED; } CAResult_t result = CALEGattSetCallbacks(); if (CA_STATUS_OK != result) { OIC_LOG(ERROR, TAG, "CABleGattSetCallbacks Failed"); - ca_mutex_unlock(g_LEClientStateMutex); + oc_mutex_unlock(g_LEClientStateMutex); CATerminateLEGattClient(); - return; + return CA_STATUS_FAILED; } g_isLEGattClientStarted = true; - ca_mutex_unlock(g_LEClientStateMutex); + oc_mutex_unlock(g_LEClientStateMutex); - ca_mutex_lock(g_LEClientThreadPoolMutex); + oc_mutex_lock(g_LEClientThreadPoolMutex); if (NULL == g_LEClientThreadPool) { OIC_LOG(ERROR, TAG, "gBleServerThreadPool is NULL"); CATerminateGattClientMutexVariables(); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - return; + oc_mutex_unlock(g_LEClientThreadPoolMutex); + return CA_STATUS_FAILED; } result = ca_thread_pool_add_task(g_LEClientThreadPool, CAStartTimerThread, - NULL); + NULL, NULL); if (CA_STATUS_OK != result) { OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed"); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - return; + CATerminateGattClientMutexVariables(); + oc_mutex_unlock(g_LEClientThreadPoolMutex); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_LEClientThreadPoolMutex); - - OIC_LOG(DEBUG, TAG, "Giving the control to threadPool"); - - GMainContext *thread_context = g_main_context_new(); - - g_eventLoop = g_main_loop_new(thread_context, FALSE); - - g_main_context_push_thread_default(thread_context); - - g_main_loop_run(g_eventLoop); + oc_mutex_unlock(g_LEClientThreadPoolMutex); OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } void CAStartTimerThread(void *data) { + (void)data; + OIC_LOG(DEBUG, TAG, "IN"); while (g_isLEGattClientStarted) { - ca_mutex_lock(g_multicastDataListMutex); + oc_mutex_lock(g_multicastDataListMutex); if (!g_isMulticastInProgress) { OIC_LOG(DEBUG, TAG, "waiting...."); - ca_cond_wait(g_startTimerCond, g_multicastDataListMutex); + oc_cond_wait(g_startTimerCond, g_multicastDataListMutex); OIC_LOG(DEBUG, TAG, "Wake up"); g_isMulticastInProgress = true; + + if (!g_isLEGattClientStarted) + { + break; + } } // Timed conditional wait for stopping the scan. - CAWaitResult_t ret = ca_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex, + OCWaitResult_t ret = oc_cond_wait_for(g_scanningTimeCond, g_multicastDataListMutex, TIMEOUT); - if (CA_WAIT_TIMEDOUT == ret) + if (OC_WAIT_TIMEDOUT == ret) { OIC_LOG(DEBUG, TAG, "Scan is timed Out"); // Call stop scan. @@ -451,14 +529,14 @@ void CAStartTimerThread(void *data) u_arraylist_destroy(g_multicastDataList); g_multicastDataList = NULL; - ca_mutex_lock(g_deviceDiscoveredListMutex); + oc_mutex_lock(g_deviceDiscoveredListMutex); u_arraylist_destroy(g_deviceDiscoveredList); g_deviceDiscoveredList = NULL; - ca_mutex_unlock(g_deviceDiscoveredListMutex); + oc_mutex_unlock(g_deviceDiscoveredListMutex); g_isMulticastInProgress = false; } - ca_mutex_unlock(g_multicastDataListMutex); + oc_mutex_unlock(g_multicastDataListMutex); } OIC_LOG(DEBUG, TAG, "OUT"); @@ -468,12 +546,12 @@ void CAStopLEGattClient() { OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_lock(g_LEClientStateMutex); + oc_mutex_lock(g_LEClientStateMutex); if (false == g_isLEGattClientStarted) { OIC_LOG(ERROR, TAG, "Gatt Client is not running to stop"); - ca_mutex_unlock(g_LEClientStateMutex); + oc_mutex_unlock(g_LEClientStateMutex); return; } @@ -481,33 +559,39 @@ void CAStopLEGattClient() CALEGattStopDeviceScanning(); + // this flag should be set before signal g_startTimerCond. + // since scan thread can be stopped through this flag. g_isLEGattClientStarted = false; // Signal the conditions waiting in Start timer. - ca_cond_signal(g_startTimerCond); - ca_cond_signal(g_scanningTimeCond); + oc_cond_signal(g_startTimerCond); + oc_cond_signal(g_scanningTimeCond); // Destroy the multicast data list and device list if not empty. if (NULL != g_multicastDataList) { - ca_mutex_lock(g_multicastDataListMutex); + oc_mutex_lock(g_multicastDataListMutex); u_arraylist_destroy(g_multicastDataList); g_multicastDataList = NULL; - ca_mutex_unlock(g_multicastDataListMutex); + oc_mutex_unlock(g_multicastDataListMutex); } if (NULL != g_deviceDiscoveredList) { - ca_mutex_lock(g_deviceDiscoveredListMutex); + oc_mutex_lock(g_deviceDiscoveredListMutex); u_arraylist_destroy(g_deviceDiscoveredList); g_deviceDiscoveredList = NULL; - ca_mutex_unlock(g_deviceDiscoveredListMutex); + oc_mutex_unlock(g_deviceDiscoveredListMutex); } - ca_mutex_lock(g_LEServerListMutex); + oc_mutex_lock(g_LEServerListMutex); CAFreeLEServerList(g_LEServerList); g_LEServerList = NULL; - ca_mutex_unlock(g_LEServerListMutex); + oc_mutex_unlock(g_LEServerListMutex); + + oc_mutex_lock(g_threadWriteCharacteristicMutex); + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); CAResetRegisteredServiceCount(); @@ -519,7 +603,7 @@ void CAStopLEGattClient() } if (context_event_loop) { - OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %x", context_event_loop); + OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %p", (void *)context_event_loop); g_main_context_wakeup(context_event_loop); // Kill g main loops and kill threads. @@ -530,7 +614,7 @@ void CAStopLEGattClient() OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL"); } - ca_mutex_unlock(g_LEClientStateMutex); + oc_mutex_unlock(g_LEClientStateMutex); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -562,90 +646,110 @@ CAResult_t CAInitGattClientMutexVariables() OIC_LOG(DEBUG, TAG, "IN"); if (NULL == g_LEClientStateMutex) { - g_LEClientStateMutex = ca_mutex_new(); + g_LEClientStateMutex = oc_mutex_new(); if (NULL == g_LEClientStateMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_LEServerListMutex) { - g_LEServerListMutex = ca_mutex_new(); + g_LEServerListMutex = oc_mutex_new(); if (NULL == g_LEServerListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_LEReqRespClientCbMutex) { - g_LEReqRespClientCbMutex = ca_mutex_new(); + g_LEReqRespClientCbMutex = oc_mutex_new(); if (NULL == g_LEReqRespClientCbMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_LEClientThreadPoolMutex) { - g_LEClientThreadPoolMutex = ca_mutex_new(); + g_LEClientThreadPoolMutex = oc_mutex_new(); if (NULL == g_LEClientThreadPoolMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_LEClientConnectMutex) { - g_LEClientConnectMutex = ca_mutex_new(); + g_LEClientConnectMutex = oc_mutex_new(); if (NULL == g_LEClientConnectMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_multicastDataListMutex) { - g_multicastDataListMutex = ca_mutex_new(); + g_multicastDataListMutex = oc_mutex_new(); if (NULL == g_multicastDataListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_deviceDiscoveredListMutex) { - g_deviceDiscoveredListMutex = ca_mutex_new(); + g_deviceDiscoveredListMutex = oc_mutex_new(); if (NULL == g_deviceDiscoveredListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadWriteCharacteristicMutex) + { + g_threadWriteCharacteristicMutex = oc_mutex_new(); + if (NULL == g_threadWriteCharacteristicMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_startTimerCond) { - g_startTimerCond = ca_cond_new(); + g_startTimerCond = oc_cond_new(); if (NULL == g_startTimerCond) { - OIC_LOG(ERROR, TAG, "ca_cond_new failed"); + OIC_LOG(ERROR, TAG, "oc_cond_new failed"); return CA_STATUS_FAILED; } } if (NULL == g_scanningTimeCond) { - g_scanningTimeCond = ca_cond_new(); + g_scanningTimeCond = oc_cond_new(); if (NULL == g_scanningTimeCond) { - OIC_LOG(ERROR, TAG, "ca_cond_new failed"); + OIC_LOG(ERROR, TAG, "oc_cond_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadWriteCharacteristicCond) + { + g_threadWriteCharacteristicCond = oc_cond_new(); + if (NULL == g_threadWriteCharacteristicCond) + { + OIC_LOG(ERROR, TAG, "oc_cond_new failed"); return CA_STATUS_FAILED; } } @@ -658,33 +762,40 @@ void CATerminateGattClientMutexVariables() { OIC_LOG(DEBUG, TAG, "IN"); - ca_mutex_free(g_LEClientStateMutex); + oc_mutex_free(g_LEClientStateMutex); g_LEClientStateMutex = NULL; - ca_mutex_free(g_LEServerListMutex); + oc_mutex_free(g_LEServerListMutex); g_LEServerListMutex = NULL; - ca_mutex_free(g_LEReqRespClientCbMutex); + oc_mutex_free(g_LEReqRespClientCbMutex); g_LEReqRespClientCbMutex = NULL; - ca_mutex_free(g_LEClientConnectMutex); + oc_mutex_free(g_LEClientConnectMutex); g_LEClientConnectMutex = NULL; - ca_mutex_free(g_LEClientThreadPoolMutex); + oc_mutex_free(g_LEClientThreadPoolMutex); g_LEClientThreadPoolMutex = NULL; - ca_mutex_free(g_multicastDataListMutex); + oc_mutex_free(g_multicastDataListMutex); g_multicastDataListMutex = NULL; - ca_mutex_free(g_deviceDiscoveredListMutex); + oc_mutex_free(g_deviceDiscoveredListMutex); g_deviceDiscoveredListMutex = NULL; - ca_cond_free(g_startTimerCond); + oc_mutex_free(g_threadWriteCharacteristicMutex); + g_threadWriteCharacteristicMutex = NULL; + + oc_cond_free(g_startTimerCond); g_startTimerCond = NULL; - ca_cond_free(g_scanningTimeCond); + oc_cond_free(g_scanningTimeCond); g_scanningTimeCond = NULL; + oc_cond_free(g_threadWriteCharacteristicCond); + g_threadWriteCharacteristicCond = NULL; + g_isSignalSetFlag = false; + OIC_LOG(DEBUG, TAG, "OUT"); } @@ -692,15 +803,6 @@ CAResult_t CALEGattSetCallbacks() { OIC_LOG(DEBUG, TAG, "IN"); - int ret = bt_gatt_set_connection_state_changed_cb(CALEGattConnectionStateChangedCb, NULL); - if (BT_ERROR_NONE != ret) - { - OIC_LOG_V(ERROR, TAG, - "bt_gatt_set_connection_state_changed_cb Failed with return as [%s ]", - CALEGetErrorMsg(ret)); - return CA_STATUS_FAILED; - } - OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } @@ -781,21 +883,65 @@ CAResult_t CALEGattConnect(const char *remoteAddress) VERIFY_NON_NULL_RET(remoteAddress, TAG, "remote address is NULL", CA_STATUS_FAILED); - ca_mutex_lock(g_LEClientConnectMutex); - - int ret = bt_gatt_connect(remoteAddress, true); - + oc_mutex_lock(g_LEClientConnectMutex); + bool isConnected = false; + int ret = bt_device_is_profile_connected(remoteAddress, BT_PROFILE_GATT, &isConnected); if (BT_ERROR_NONE != ret) { - OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ", + OIC_LOG_V(ERROR, TAG, "bt_device_is_profile_connected Failed with ret value [%s] ", CALEGetErrorMsg(ret)); - ca_mutex_unlock(g_LEClientConnectMutex); + oc_mutex_unlock(g_LEClientConnectMutex); return CA_STATUS_FAILED; } - ca_mutex_unlock(g_LEClientConnectMutex); + + CAResult_t result = CA_STATUS_OK; + if (!isConnected) + { + ret = bt_gatt_connect(remoteAddress, true); + + if (BT_ERROR_NONE != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ", + CALEGetErrorMsg(ret)); + oc_mutex_unlock(g_LEClientConnectMutex); + return CA_STATUS_FAILED; + } + } + else + { + OIC_LOG_V(INFO, TAG, "Remote address[%s] is already connected", + remoteAddress); + char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + OIC_LOG(ERROR, TAG, "addr is NULL"); + oc_mutex_unlock(g_LEClientConnectMutex); + return CA_STATUS_FAILED; + } + + oc_mutex_lock(g_LEClientThreadPoolMutex); + if (NULL == g_LEClientThreadPool) + { + OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); + OICFree(addr); + oc_mutex_unlock(g_LEClientThreadPoolMutex); + oc_mutex_unlock(g_LEClientConnectMutex); + return CA_STATUS_FAILED; + } + + result = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, + addr, NULL); + if (CA_STATUS_OK != result) + { + OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", result); + OICFree(addr); + } + oc_mutex_unlock(g_LEClientThreadPoolMutex); + } + oc_mutex_unlock(g_LEClientConnectMutex); OIC_LOG(DEBUG, TAG, "OUT"); - return CA_STATUS_OK; + return result; } CAResult_t CALEGattDisConnect(const char *remoteAddress) @@ -809,7 +955,7 @@ CAResult_t CALEGattDisConnect(const char *remoteAddress) if (BT_ERROR_NONE != ret) { - OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%d] ", + OIC_LOG_V(ERROR, TAG, "bt_gatt_disconnect Failed with ret value [%s] ", CALEGetErrorMsg(ret)); return CA_STATUS_FAILED; } @@ -843,13 +989,50 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) VERIFY_NON_NULL_RET(remoteAddress, TAG, "remote address is NULL", CA_STATUS_FAILED); + LEServerInfo *leServerInfo = NULL; + CAResult_t result = CA_STATUS_FAILED; + + oc_mutex_lock(g_LEServerListMutex); + result = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo); + oc_mutex_unlock(g_LEServerListMutex); + + if (CA_STATUS_OK == result) + { + OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", leServerInfo->remoteAddress); + + // Send the data of pending multicast data list if any. + if (g_multicastDataList) + { + oc_mutex_lock(g_multicastDataListMutex); + uint32_t arrayLength = u_arraylist_length(g_multicastDataList); + for (uint32_t i = 0; i < arrayLength; i++) + { + CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i); + if (NULL == multicastData) + { + OIC_LOG(DEBUG, TAG, "multicastData is NULL"); + continue; + } + CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data, + multicastData->dataLen, LE_UNICAST, 0); + } + oc_mutex_unlock(g_multicastDataListMutex); + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; + } + else + { + OIC_LOG_V(INFO, TAG, "CAGetLEServerInfo [%s] is failed, %d", remoteAddress, result); + } + bt_gatt_client_h clientHandle = NULL; int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle); if (BT_ERROR_NONE != ret || NULL == clientHandle) { OIC_LOG_V(ERROR, TAG, "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret)); - CALEGattDisConnect(remoteAddress); return CA_STATUS_FAILED; } @@ -860,7 +1043,6 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) OIC_LOG_V(ERROR, TAG, "bt_gatt_client_get_service Failed with ret value [%s] ", CALEGetErrorMsg(ret)); bt_gatt_client_destroy(clientHandle); - CALEGattDisConnect(remoteAddress); return CA_STATUS_FAILED; } @@ -895,6 +1077,14 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) //TODO: This data has to be freed while unsetting the callback. char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + OIC_LOG(ERROR, TAG, "addr is NULL"); + bt_gatt_client_destroy(clientHandle); + CALEGattDisConnect(remoteAddress); + return CA_STATUS_FAILED; + } + ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle, CALEGattCharacteristicChangedCb, (void *)addr); @@ -921,23 +1111,39 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) serverInfo->writeChar = writeChrHandle; serverInfo->remoteAddress = OICStrdup(remoteAddress); - ca_mutex_lock(g_LEServerListMutex); - CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo); + oc_mutex_lock(g_LEServerListMutex); + result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo); if (CA_STATUS_OK != result) { - OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed"); + OIC_LOG(ERROR, TAG, "CAAddLEServerInfoToList failed"); bt_gatt_client_destroy(clientHandle); CALEGattDisConnect(remoteAddress); return CA_STATUS_FAILED; } - ca_mutex_unlock(g_LEServerListMutex); + oc_mutex_unlock(g_LEServerListMutex); + + oc_mutex_lock(g_deviceDiscoveredListMutex); + // Add the the device Discovered list. + if (NULL == g_deviceDiscoveredList) + { + g_deviceDiscoveredList = u_arraylist_create(); + } + char *deviceAddr = OICStrdup(remoteAddress); + if (NULL == deviceAddr) + { + OIC_LOG_V(ERROR, TAG, "Device address is NULL"); + oc_mutex_unlock(g_deviceDiscoveredListMutex); + return CA_STATUS_FAILED; + } + u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr); + oc_mutex_unlock(g_deviceDiscoveredListMutex); // Send the data of pending multicast data list if any. if (g_multicastDataList) { - ca_mutex_lock(g_multicastDataListMutex); + oc_mutex_lock(g_multicastDataListMutex); uint32_t arrayLength = u_arraylist_length(g_multicastDataList); - for (int i = 0; i < arrayLength; i++) + for (uint32_t i = 0; i < arrayLength; i++) { CALEData_t *multicastData = u_arraylist_get(g_multicastDataList, i); if (NULL == multicastData) @@ -948,7 +1154,7 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) CAUpdateCharacteristicsToGattServer(remoteAddress, multicastData->data, multicastData->dataLen, LE_UNICAST, 0); } - ca_mutex_unlock(g_multicastDataListMutex); + oc_mutex_unlock(g_multicastDataListMutex); } OIC_LOG(DEBUG, TAG, "OUT"); @@ -972,7 +1178,7 @@ CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, LEServerInfo *leServerInfo = NULL; CAResult_t ret = CA_STATUS_FAILED; - ca_mutex_lock(g_LEServerListMutex); + oc_mutex_lock(g_LEServerListMutex); if (LE_UNICAST == type) { ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo); @@ -981,7 +1187,7 @@ CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, { ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo); } - ca_mutex_unlock(g_LEServerListMutex); + oc_mutex_unlock(g_LEServerListMutex); if (CA_STATUS_OK != ret) { @@ -1014,6 +1220,26 @@ CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, return CA_STATUS_FAILED; } + // wait for callback for write Characteristic with success to sent data + OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag); + oc_mutex_lock(g_threadWriteCharacteristicMutex); + if (!g_isSignalSetFlag) + { + OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success"); + if (OC_WAIT_SUCCESS != oc_cond_wait_for(g_threadWriteCharacteristicCond, + g_threadWriteCharacteristicMutex, + WAIT_TIME_WRITE_CHARACTERISTIC)) + { + OIC_LOG(ERROR, TAG, "there is no response. write has failed"); + g_isSignalSetFlag = false; + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + return CA_SEND_FAILED; + } + } + // reset flag set by writeCharacteristic Callback + g_isSignalSetFlag = false; + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } @@ -1064,13 +1290,13 @@ CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t memcpy(multicastData->data, data, dataLen); multicastData->dataLen = dataLen; - ca_mutex_lock(g_multicastDataListMutex); + oc_mutex_lock(g_multicastDataListMutex); if (NULL == g_multicastDataList) { g_multicastDataList = u_arraylist_create(); } u_arraylist_add(g_multicastDataList, (void *)multicastData); - ca_mutex_unlock(g_multicastDataListMutex); + oc_mutex_unlock(g_multicastDataListMutex); // Start the scanning. CAResult_t result = CALEGattStartDeviceScanning(); @@ -1081,11 +1307,42 @@ CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t } // Start the timer by signalling it. - ca_cond_signal(g_startTimerCond); + oc_cond_signal(g_startTimerCond); exit: OIC_LOG(DEBUG, TAG, "OUT "); return CA_STATUS_OK; } +bool CALEClientIsConnected(const char* address) +{ + (void)address; + //@Todo + return true; +} + +uint16_t CALEClientGetMtuSize(const char* address) +{ + VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE); + //@Todo + //it should be implemented after update Tizen 3.0 + return CA_DEFAULT_BLE_MTU_SIZE; +} + +CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize) +{ + (void)mtuSize; + + VERIFY_NON_NULL(address, TAG, "address is null"); + //@Todo + //it should be implemented after update Tizen 3.0 + return CA_NOT_SUPPORTED; +} +CAResult_t CALEClientSendNegotiationMessage(const char* address) +{ + OIC_LOG_V(DEBUG, TAG, "CALEClientSendNegotiationMessage(%s)", address); + //@Todo + //it will be implemented when tizen public 3.0 is released. + return CA_NOT_SUPPORTED; +}