X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_le_adapter%2Ftizen%2Fcaleclient.c;h=7c5f6c872407bb498192a587fa000e8016d4a4d0;hb=031f3c110197a54e9b8c759cb246b2eb918bd937;hp=3732bc9d0ff7acd60b060816c89bb5bde9b3dec5;hpb=cf56a410a2150ae474c676e7e6d01b89552a4873;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 old mode 100644 new mode 100755 index 3732bc9..7c5f6c8 --- 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" @@ -44,45 +43,86 @@ */ #define TAG "OIC_CA_LE_CLIENT" +#define RETRY_COUNT 1 #define MICROSECS_PER_SEC 1000000 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC +//For custom uuid ble server +#define CA_GATT_CUSTOM_UUID "4209" +#define CA_GATT_CUSTOM_UUID2 "4204" +#define CUSTOM_UUID_LEN 4 +#define MICROSECS_PER_SEC 1000000 + +static const int samsung_code = 117; +static int g_retrycount = 0; +static int retry_flag = 0; uint64_t const TIMEOUT = 30 * MICROSECS_PER_SEC; /** + * Mutex to call connect only after disconnect during retry + */ +static oc_mutex g_isDisconnectedMutex = NULL; + +/** + * Condition for calling connect during connection retry + */ +static oc_cond g_LEDisconnectedCond = NULL; + +/** + * Flag to check if scanning is in progress + */ +static bool g_isScanningInProgress = false; + +/** + * Mutex to synchronize access to g_isScanningInProgress + */ +static oc_mutex g_isScanningInProgressMutex = NULL; + +/** + * Flag to check if connection is in progress + */ +static bool g_isConnectionInProgress = false; + +/** + * Mutex to synchronize access to g_isConnectionInProgress + */ +static oc_mutex g_isConnectionInProgressMutex = NULL; + +/** * Flag to check if multicast is already in progress. */ static bool g_isMulticastInProgress = false; /** - * Pending multicast data list to be sent. + * Flag to check if unicast scan is in progress */ -static u_arraylist_t *g_multicastDataList = NULL; +static bool g_isUnicastScanInProgress = false; /** - * Mutex to synchronize the access to Pending multicast data list. + * Mutex to synchronize access to g_isMulticastInProgress + * and g_isUnicastScanInProgress */ -static ca_mutex g_multicastDataListMutex = NULL; +static oc_mutex g_scanMutex = NULL; /** - * List of devices discovered. + * Pending multicast data list to be sent. */ -static u_arraylist_t *g_deviceDiscoveredList = NULL; +static u_arraylist_t *g_multicastDataList = NULL; /** - * Mutex to synchronize the access to discovered devices list. + * Mutex to synchronize the access to Pending multicast data list. */ -static ca_mutex g_deviceDiscoveredListMutex = NULL; +static oc_mutex g_multicastDataListMutex = 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. @@ -92,7 +132,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. @@ -103,34 +143,44 @@ 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 ca_mutex g_threadWriteCharacteristicMutex = NULL; +static oc_mutex g_threadWriteCharacteristicMutex = NULL; /** * Condition for Writing characteristic. */ -static ca_cond g_threadWriteCharacteristicCond = NULL; +static oc_cond g_threadWriteCharacteristicCond = NULL; + +/** + * Mutex to synchronize the task for MTU Changed. + */ +static oc_mutex g_threadMTUChangedMutex = NULL; + +/** + * Condition for MTU Changed. + */ +static oc_cond g_threadMTUChangedCond = NULL; /** * Flag to check status of write characteristic. @@ -158,127 +208,272 @@ static GMainLoop *g_eventLoop = NULL; */ static ca_thread_pool_t g_LEClientThreadPool = NULL; -bt_scan_filter_h g_scanFilter = NULL; - -bool CALEIsDeviceDiscovered(const char * address) -{ - OIC_LOG(DEBUG, TAG, "IN"); - if (g_deviceDiscoveredList) - { - ca_mutex_lock(g_deviceDiscoveredListMutex); - uint32_t arrayLength = u_arraylist_length(g_deviceDiscoveredList); - for (int 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); - return true; - } - - } - ca_mutex_unlock(g_deviceDiscoveredListMutex); - } - OIC_LOG(DEBUG, TAG, "OUT"); - return false; -} - 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 CALEGattClientMTUChangedCb(bt_gatt_client_h client_handle, const bt_gatt_client_att_mtu_info_s *mtu_info, void *user_data) +{ + OIC_LOG(DEBUG, TAG, "IN"); + oc_mutex_lock(g_threadMTUChangedMutex); + OIC_LOG(DEBUG, TAG, "MTU changed signal"); + oc_cond_signal(g_threadMTUChangedCond); + oc_mutex_unlock(g_threadMTUChangedMutex); 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 { - ca_mutex_lock(g_threadWriteCharacteristicMutex); + oc_mutex_lock(g_threadWriteCharacteristicMutex); OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal"); g_isSignalSetFlag = true; - ca_cond_signal(g_threadWriteCharacteristicCond); - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + 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 CALEGattConnectionStateChanged(bool connected, const char *remoteAddress) +CAResult_t CALEGattInitiateConnection(const char *remoteAddress) { - OIC_LOG(DEBUG, TAG, "IN "); + OIC_LOG(DEBUG, TAG, "IN"); - VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL"); + oc_mutex_lock(g_isConnectionInProgressMutex); + if (g_isConnectionInProgress) + { + oc_mutex_unlock(g_isConnectionInProgressMutex); + OIC_LOG(DEBUG, TAG, "Connection already in progress, cannot initiate new connection"); + return CA_STATUS_FAILED; + } + g_isConnectionInProgress = true; + // Set gatt connect retry count + g_retrycount = RETRY_COUNT; + oc_mutex_unlock(g_isConnectionInProgressMutex); + + // Pause the scanning + CALEGattStopDeviceScanning(); - // Start the scanning. - CAResult_t ret = CALEGattStartDeviceScanning(); - if (CA_STATUS_OK != ret) + OIC_LOG_V(DEBUG, TAG, + "Trying to do Gatt connection to [%s]", remoteAddress); + + oc_mutex_lock(g_LEClientThreadPoolMutex); + if (NULL == g_LEClientThreadPool) + { + oc_mutex_unlock(g_LEClientThreadPoolMutex); + OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); + return CA_STATUS_FAILED; + } + + char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + oc_mutex_unlock(g_LEClientThreadPoolMutex); + OIC_LOG(ERROR, TAG, "OICStrdup failed"); + return CA_STATUS_FAILED; + } + + CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr, NULL); + oc_mutex_unlock(g_LEClientThreadPoolMutex); + if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed"); + OIC_LOG_V(ERROR, TAG, + "ca_thread_pool_add_task failed with ret [%d]", res); + OICFree(addr); + return CA_STATUS_FAILED; } - // Signal the start timer. - ca_cond_signal(g_scanningTimeCond); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} + +void CALEGattConnectionStateChanged(bool connected, const char *remoteAddress) +{ + OIC_LOG(DEBUG, TAG, "IN "); + + VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address is NULL"); if (!connected) { OIC_LOG_V(DEBUG, TAG, "DisConnected from [%s] ", remoteAddress); + if(!retry_flag) + { + oc_mutex_lock(g_LEServerListMutex); + CARemoveLEServerInfoFromList(&g_LEServerList, remoteAddress); + oc_mutex_unlock(g_LEServerListMutex); + } + else + { + oc_mutex_lock(g_isDisconnectedMutex); + oc_cond_signal(g_LEDisconnectedCond); + oc_mutex_unlock(g_isDisconnectedMutex); + } + retry_flag = 0; } else { OIC_LOG_V(DEBUG, TAG, "Connected to [%s] ", remoteAddress); - char *addr = OICStrdup(remoteAddress); + oc_mutex_lock(g_isConnectionInProgressMutex); + g_isConnectionInProgress = false; + oc_mutex_unlock(g_isConnectionInProgressMutex); - ca_mutex_lock(g_LEClientThreadPoolMutex); + LEServerInfo *serverInfo = NULL; + oc_mutex_lock(g_LEServerListMutex); + if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG_V(ERROR, TAG, "Could not get server info for [%s]", remoteAddress); + return; + } + + serverInfo->status = LE_STATUS_CONNECTED; + oc_mutex_unlock(g_LEServerListMutex); + oc_mutex_lock(g_LEClientThreadPoolMutex); if (NULL == g_LEClientThreadPool) { + oc_mutex_unlock(g_LEClientThreadPoolMutex); OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); - OICFree(addr); - ca_mutex_unlock(g_LEClientThreadPoolMutex); return; } - ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, - addr); + char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + oc_mutex_unlock(g_LEClientThreadPoolMutex); + OIC_LOG(ERROR, TAG, "addr is NULL"); + return; + } + + CAResult_t ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, + addr, NULL); + oc_mutex_unlock(g_LEClientThreadPoolMutex); 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); } OIC_LOG(DEBUG, TAG, "OUT"); } +static bool CALEIsHaveServiceImpl(bt_adapter_le_device_scan_result_info_s *scanInfo, + const char *service_uuid, + bt_adapter_le_packet_type_e pkt_type) +{ + bool ret = false; + char **uuids = NULL; + int count = 0; + int result = 0; + + result = bt_adapter_le_get_scan_result_service_uuids(scanInfo, + pkt_type, &uuids, &count); + if (result == BT_ERROR_NONE && NULL != uuids) + { + for (int 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); + } + + if(ret == false){ + char *man_data = NULL; + int man_data_len; + int man_id; + result = bt_adapter_le_get_scan_result_manufacturer_data(scanInfo, + pkt_type, &man_id, &man_data, &man_data_len); + + if (result == BT_ERROR_NONE && NULL != man_data) + { + int pos =0; + char *compare_man_data = OICCalloc(1, (man_data_len*2)+1); + if (!compare_man_data) + { + OIC_LOG(ERROR, TAG, "Memory allocation failed for compare_man_data"); + OICFree(man_data); + return false; + } + + for(int i=0;iremote_address); + ret = true; + } + OICFree(compare_man_data); + OICFree(man_data); + } + } + return ret; +} + +static bool CALEIsHaveService(bt_adapter_le_device_scan_result_info_s *scanInfo, + const char *service_uuid) +{ + return + // For arduino servers, scan response will give the UUIDs advertised. + CALEIsHaveServiceImpl(scanInfo, service_uuid, + BT_ADAPTER_LE_PACKET_SCAN_RESPONSE) || + // For android/tizen servers, advertising packet will give the UUIDs. + CALEIsHaveServiceImpl(scanInfo, service_uuid, + BT_ADAPTER_LE_PACKET_ADVERTISING); +} + 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"); @@ -291,53 +486,87 @@ void CALEAdapterScanResultCb(int result, bt_adapter_le_device_scan_result_info_s scanInfo->adv_data_len, scanInfo->scan_data_len, scanInfo->rssi, scanInfo->address_type); - // Check if device is already discovered. - if (CALEIsDeviceDiscovered(scanInfo->remote_address)) + // Check if scanning was stopped (since this callback is + // being triggered even after stopping the scan) + oc_mutex_lock(g_isScanningInProgressMutex); + if (!g_isScanningInProgress) { - OIC_LOG_V(INFO, TAG, "Device[%s] is already discovered", scanInfo->remote_address); + oc_mutex_unlock(g_isScanningInProgressMutex); + OIC_LOG(DEBUG, TAG, "Scanning not in progress, so ignoring callback"); return; } + oc_mutex_unlock(g_isScanningInProgressMutex); - // 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) || + CALEIsHaveService(scanInfo, CA_GATT_CUSTOM_UUID)|| + CALEIsHaveService(scanInfo, CA_GATT_CUSTOM_UUID2)) { - g_deviceDiscoveredList = u_arraylist_create(); - } - char *deviceAddr = OICStrdup(scanInfo->remote_address); - u_arraylist_add(g_deviceDiscoveredList, (void *) deviceAddr); - ca_mutex_unlock(g_deviceDiscoveredListMutex); + OIC_LOG_V(DEBUG, TAG, "Device [%s] supports OIC or custom service", scanInfo->remote_address); - size_t len = strlen(scanInfo->remote_address); - - char *addr = (char *)OICMalloc(sizeof(char) * (len + 1)); - VERIFY_NON_NULL_VOID(addr, TAG, "Malloc failed"); - - strncpy(addr, scanInfo->remote_address, len + 1); + LEServerInfo *serverInfo = NULL; + oc_mutex_lock(g_LEServerListMutex); + CAResult_t ret = CAGetLEServerInfo(g_LEServerList, scanInfo->remote_address, &serverInfo); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(DEBUG, TAG, + "Newly discovered device with address [%s] ", scanInfo->remote_address); - OIC_LOG_V(DEBUG, TAG, - "Trying to do Gatt connection to [%s]", addr); + char *addr = OICStrdup(scanInfo->remote_address); + if (NULL == addr) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Device address is NULL"); + return; + } + serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo)); + if (NULL == serverInfo) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Calloc failed"); + OICFree(addr); + return; + } + serverInfo->remoteAddress = addr; + serverInfo->status = LE_STATUS_DISCOVERED; - ca_mutex_lock(g_LEClientThreadPoolMutex); - if (NULL == g_LEClientThreadPool) - { - OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); - OICFree(addr); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - return; + if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", scanInfo->remote_address); + CAFreeLEServerInfo(serverInfo); + return; + } + }else { + OIC_LOG_V(DEBUG, TAG, + "Device Present with address [%s] ", scanInfo->remote_address); + + if(serverInfo->status == LE_STATUS_UNICAST_PENDING){ + bt_gatt_client_h clientHandle = NULL; + int32_t ret = bt_gatt_client_create(serverInfo->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(serverInfo->remoteAddress); + oc_mutex_unlock(g_LEServerListMutex); + return ; + } + serverInfo->clientHandle = clientHandle; + + serverInfo->status = LE_STATUS_CONNECTION_INITIATED; + if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress)) + { + OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress); + serverInfo->status = LE_STATUS_DISCOVERED; + CADestroyLEDataList(&serverInfo->pendingDataList); + oc_mutex_unlock(g_LEServerListMutex); + return ; + } + } + } + oc_mutex_unlock(g_LEServerListMutex); } - CAResult_t res = ca_thread_pool_add_task(g_LEClientThreadPool, CAGattConnectThread, addr); - 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); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -345,9 +574,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"); } @@ -356,11 +585,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"); } @@ -374,121 +603,128 @@ 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); +#ifdef TIZEN_VD + result= ca_thread_pool_add_task(g_LEClientThreadPool, CALEClientScanThread, + NULL, NULL); + if (CA_STATUS_OK != result) + { + OIC_LOG(ERROR, TAG, "ca_thread_pool_add_task failed"); + CATerminateGattClientMutexVariables(); + oc_mutex_unlock(g_LEClientThreadPoolMutex); + return CA_STATUS_FAILED; + } +#endif + oc_mutex_unlock(g_LEClientThreadPoolMutex); - g_main_context_push_thread_default(thread_context); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} - g_main_loop_run(g_eventLoop); +#ifdef TIZEN_VD +void CALEClientScanThread() +{ + oc_mutex_lock(g_scanMutex); + if (!g_isMulticastInProgress && !g_isUnicastScanInProgress) + { + CAResult_t result = CALEGattStartDeviceScanning(); + if (CA_STATUS_OK != result) + { + oc_mutex_unlock(g_scanMutex); + OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning failed"); + return ; + } + g_isUnicastScanInProgress = true; + // Start Timer + oc_cond_signal(g_startTimerCond); + } + else + { + g_isUnicastScanInProgress = true; + // Reset Timer + oc_cond_signal(g_scanningTimeCond); + } + oc_mutex_unlock(g_scanMutex); OIC_LOG(DEBUG, TAG, "OUT"); + return ; } +#endif void CAStartTimerThread(void *data) { + (void)data; + OIC_LOG(DEBUG, TAG, "IN"); while (g_isLEGattClientStarted) { - ca_mutex_lock(g_multicastDataListMutex); - if (!g_isMulticastInProgress) + oc_mutex_lock(g_scanMutex); + if (!g_isMulticastInProgress && !g_isUnicastScanInProgress) { OIC_LOG(DEBUG, TAG, "waiting...."); - ca_cond_wait(g_startTimerCond, g_multicastDataListMutex); + oc_cond_wait(g_startTimerCond, g_scanMutex); OIC_LOG(DEBUG, TAG, "Wake up"); - g_isMulticastInProgress = true; } // 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_scanMutex, TIMEOUT); - if (CA_WAIT_TIMEDOUT == ret) + if (OC_WAIT_TIMEDOUT == ret) { OIC_LOG(DEBUG, TAG, "Scan is timed Out"); // Call stop scan. CALEGattStopDeviceScanning(); - // Clear the data list and device list. - u_arraylist_destroy(g_multicastDataList); - g_multicastDataList = NULL; - - ca_mutex_lock(g_deviceDiscoveredListMutex); - u_arraylist_destroy(g_deviceDiscoveredList); - g_deviceDiscoveredList = NULL; - ca_mutex_unlock(g_deviceDiscoveredListMutex); - - g_isMulticastInProgress = false; + if (g_isMulticastInProgress) + { + oc_mutex_lock(g_multicastDataListMutex); + // Clear the data list and device list. + u_arraylist_destroy(g_multicastDataList); + g_multicastDataList = NULL; + oc_mutex_unlock(g_multicastDataListMutex); + g_isMulticastInProgress = false; + } + g_isUnicastScanInProgress = false; } - ca_mutex_unlock(g_multicastDataListMutex); + oc_mutex_unlock(g_scanMutex); } OIC_LOG(DEBUG, TAG, "OUT"); @@ -498,12 +734,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; } @@ -514,36 +750,26 @@ void CAStopLEGattClient() 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); - } - - if (NULL != g_deviceDiscoveredList) - { - ca_mutex_lock(g_deviceDiscoveredListMutex); - u_arraylist_destroy(g_deviceDiscoveredList); - g_deviceDiscoveredList = NULL; - ca_mutex_unlock(g_deviceDiscoveredListMutex); + oc_mutex_unlock(g_multicastDataListMutex); } - 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); - ca_mutex_lock(g_threadWriteCharacteristicMutex); - ca_cond_signal(g_threadWriteCharacteristicCond); - ca_mutex_unlock(g_threadWriteCharacteristicMutex); - - CAResetRegisteredServiceCount(); + oc_mutex_lock(g_threadWriteCharacteristicMutex); + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); GMainContext *context_event_loop = NULL; // Required for waking up the thread which is running in gmain loop @@ -553,7 +779,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. @@ -564,7 +790,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"); } @@ -596,114 +822,175 @@ 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_isScanningInProgressMutex) + { + g_isScanningInProgressMutex = oc_mutex_new(); + if (NULL == g_isScanningInProgressMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_isConnectionInProgressMutex) + { + g_isConnectionInProgressMutex = oc_mutex_new(); + if (NULL == g_isConnectionInProgressMutex) + { + 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) + if (NULL == g_scanMutex) { - g_deviceDiscoveredListMutex = ca_mutex_new(); - if (NULL == g_deviceDiscoveredListMutex) + g_scanMutex = oc_mutex_new(); + if (NULL == g_scanMutex) { - 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 = ca_mutex_new(); + g_threadWriteCharacteristicMutex = oc_mutex_new(); if (NULL == g_threadWriteCharacteristicMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadMTUChangedMutex) + { + g_threadMTUChangedMutex = oc_mutex_new(); + if (NULL == g_threadMTUChangedMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_isDisconnectedMutex) + { + g_isDisconnectedMutex = oc_mutex_new(); + if (NULL == g_isDisconnectedMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_LEDisconnectedCond) + { + g_LEDisconnectedCond = oc_cond_new(); + if (NULL == g_LEDisconnectedCond) + { + OIC_LOG(ERROR, TAG, "oc_cond_new 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 = ca_cond_new(); + g_threadWriteCharacteristicCond = oc_cond_new(); if (NULL == g_threadWriteCharacteristicCond) { - OIC_LOG(ERROR, TAG, "ca_cond_new failed"); + OIC_LOG(ERROR, TAG, "oc_cond_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_threadMTUChangedCond) + { + g_threadMTUChangedCond = oc_cond_new(); + if (NULL == g_threadMTUChangedCond) + { + OIC_LOG(ERROR, TAG, "oc_cond_new failed"); return CA_STATUS_FAILED; } } + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } @@ -712,40 +999,58 @@ 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_isScanningInProgressMutex); + g_isScanningInProgressMutex = NULL; + + oc_mutex_free(g_isConnectionInProgressMutex); + g_isConnectionInProgressMutex = NULL; + + oc_mutex_free(g_multicastDataListMutex); g_multicastDataListMutex = NULL; - ca_mutex_free(g_deviceDiscoveredListMutex); - g_deviceDiscoveredListMutex = NULL; + oc_mutex_free(g_scanMutex); + g_scanMutex = NULL; - ca_mutex_free(g_threadWriteCharacteristicMutex); + oc_mutex_free(g_threadWriteCharacteristicMutex); g_threadWriteCharacteristicMutex = NULL; - ca_cond_free(g_startTimerCond); + oc_mutex_free(g_threadMTUChangedMutex); + g_threadMTUChangedMutex = NULL; + + oc_mutex_free(g_isDisconnectedMutex); + g_isDisconnectedMutex = NULL; + + oc_cond_free(g_LEDisconnectedCond); + g_LEDisconnectedCond = NULL; + + oc_cond_free(g_startTimerCond); g_startTimerCond = NULL; - ca_cond_free(g_scanningTimeCond); + oc_cond_free(g_scanningTimeCond); g_scanningTimeCond = NULL; - ca_cond_free(g_threadWriteCharacteristicCond); + oc_cond_free(g_threadWriteCharacteristicCond); g_threadWriteCharacteristicCond = NULL; g_isSignalSetFlag = false; + oc_cond_free(g_threadMTUChangedCond); + g_threadMTUChangedCond = NULL; + OIC_LOG(DEBUG, TAG, "OUT"); } @@ -763,14 +1068,19 @@ void CALEGattUnSetCallbacks() bt_gatt_unset_connection_state_changed_cb(); - int numOfServersConnected = CAGetRegisteredServiceCount(); - LEServerInfo *leServerInfo = NULL; - - for (int32_t index = 0; index < numOfServersConnected; index++) + oc_mutex_lock(g_LEServerListMutex); + LEServerInfoList *curNode = g_LEServerList; + while (curNode) { - CAGetLEServerInfoByPosition(g_LEServerList, index, &leServerInfo); - bt_gatt_client_unset_characteristic_value_changed_cb(leServerInfo->readChar); + LEServerInfo *serverInfo = curNode->serverInfo; + if (serverInfo->status >= LE_STATUS_SERVICES_DISCOVERED) + { + bt_gatt_client_unset_characteristic_value_changed_cb(serverInfo->readChar); + } + curNode = curNode->next; } + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(DEBUG, TAG, "OUT"); } @@ -778,13 +1088,24 @@ CAResult_t CALEGattStartDeviceScanning() { OIC_LOG(DEBUG, TAG, "IN"); - int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL); - if(BT_ERROR_NONE != ret) + oc_mutex_lock(g_isScanningInProgressMutex); + if (!g_isScanningInProgress) { - OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]", - CALEGetErrorMsg(ret)); - return CA_STATUS_FAILED; + int ret = bt_adapter_le_start_scan(CALEAdapterScanResultCb, NULL); + if (BT_ERROR_NONE != ret) + { + oc_mutex_unlock(g_isScanningInProgressMutex); + OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_scan failed[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + g_isScanningInProgress = true; + } + else + { + OIC_LOG(DEBUG, TAG, "Ignore, scanning already in progress"); } + oc_mutex_unlock(g_isScanningInProgressMutex); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; @@ -794,12 +1115,25 @@ void CALEGattStopDeviceScanning() { OIC_LOG(DEBUG, TAG, "IN"); - int ret = bt_adapter_le_stop_scan(); - if (BT_ERROR_NONE != ret) + oc_mutex_lock(g_isScanningInProgressMutex); + if (g_isScanningInProgress) { - OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]", - CALEGetErrorMsg(ret)); + int ret = bt_adapter_le_stop_scan(); + if (BT_ERROR_NONE != ret) + { + oc_mutex_unlock(g_isScanningInProgressMutex); + OIC_LOG_V(ERROR, TAG, "bt_adapter_le_stop_scan failed[%s]", + CALEGetErrorMsg(ret)); + return; + } + g_isScanningInProgress = false; + g_isUnicastScanInProgress= false; } + else + { + OIC_LOG(DEBUG, TAG, "Ignore, scanning not in progress"); + } + oc_mutex_unlock(g_isScanningInProgressMutex); OIC_LOG(DEBUG, TAG, "OUT"); } @@ -833,62 +1167,23 @@ CAResult_t CALEGattConnect(const char *remoteAddress) VERIFY_NON_NULL_RET(remoteAddress, TAG, "remote address is NULL", CA_STATUS_FAILED); - ca_mutex_lock(g_LEClientConnectMutex); - bool isConnected = false; - int ret = bt_device_is_profile_connected(remoteAddress, BT_PROFILE_GATT, &isConnected); + oc_mutex_lock(g_LEClientConnectMutex); + CAResult_t result = CA_STATUS_OK; + +#ifdef TIZEN_VD + int ret = bt_gatt_connect(remoteAddress, true); +#else + int ret = bt_gatt_connect(remoteAddress, false); +#endif if (BT_ERROR_NONE != ret) { - OIC_LOG_V(ERROR, TAG, "bt_device_is_profile_connected Failed with ret value [%s] ", + OIC_LOG_V(ERROR, TAG, "bt_gatt_connect Failed with ret value [%s] ", CALEGetErrorMsg(ret)); - ca_mutex_unlock(g_LEClientConnectMutex); + oc_mutex_unlock(g_LEClientConnectMutex); return CA_STATUS_FAILED; } - 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)); - ca_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"); - ca_mutex_unlock(g_LEClientConnectMutex); - return CA_STATUS_FAILED; - } - - ca_mutex_lock(g_LEClientThreadPoolMutex); - if (NULL == g_LEClientThreadPool) - { - OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); - OICFree(addr); - ca_mutex_unlock(g_LEClientThreadPoolMutex); - ca_mutex_unlock(g_LEClientConnectMutex); - return CA_STATUS_FAILED; - } - - result = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, - addr); - if (CA_STATUS_OK != result) - { - OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", result); - OICFree(addr); - } - ca_mutex_unlock(g_LEClientThreadPoolMutex); - } - ca_mutex_unlock(g_LEClientConnectMutex); + oc_mutex_unlock(g_LEClientConnectMutex); OIC_LOG(DEBUG, TAG, "OUT"); return result; @@ -905,7 +1200,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; } @@ -914,7 +1209,86 @@ CAResult_t CALEGattDisConnect(const char *remoteAddress) return CA_STATUS_OK; } -void CADiscoverLEServicesThread (void *remoteAddress) +CAResult_t CAUpdateCharacteristicsToGattServerImpl(LEServerInfo *serverInfo, + const uint8_t *data, const uint32_t dataLen) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(serverInfo, TAG, "Server Info is NULL"); + + CALEGattStopDeviceScanning(); + + OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen, + serverInfo->remoteAddress); + + int result = bt_gatt_set_value(serverInfo->writeChar, (char *)data, dataLen); + + if (BT_ERROR_NONE != result) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_set_value Failed with return val [%s]", + CALEGetErrorMsg(result)); + goto exit; + } + + result = bt_gatt_client_write_value(serverInfo->writeChar, CALEGattCharacteristicWriteCb, + NULL); + if (BT_ERROR_NONE != result) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_client_write_value Failed with return val [%s]", + CALEGetErrorMsg(result)); + goto exit; + } + + // 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)) + { + g_isSignalSetFlag = false; + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + OIC_LOG(ERROR, TAG, "there is no response. write has failed"); + goto exit; + } + } + // reset flag set by writeCharacteristic Callback + g_isSignalSetFlag = false; + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + + oc_mutex_lock(g_scanMutex); + if (g_isMulticastInProgress || g_isUnicastScanInProgress) + { + if (CA_STATUS_OK != CALEGattStartDeviceScanning()) + { + OIC_LOG(ERROR, TAG, "Could not start device scanning"); + } + } + oc_mutex_unlock(g_scanMutex); + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; + +exit: + oc_mutex_lock(g_scanMutex); + if (g_isMulticastInProgress || g_isUnicastScanInProgress) + { + if (CA_STATUS_OK != CALEGattStartDeviceScanning()) + { + OIC_LOG(ERROR, TAG, "Could not start device scanning"); + } + } + oc_mutex_unlock(g_scanMutex); + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_FAILED; +} + +void CADiscoverLEServicesThread(void *remoteAddress) { OIC_LOG(DEBUG, TAG, "IN"); @@ -932,6 +1306,30 @@ void CADiscoverLEServicesThread (void *remoteAddress) OIC_LOG(DEBUG, TAG, "OUT"); } +static int CALEWaittillDisconnect(oc_mutex mutex, oc_cond cv, int wait_seconds) +{ + OIC_LOG(DEBUG, TAG, "Waiting for server to be disconnected..."); + oc_mutex_lock(mutex); + uint64_t wait_time = wait_seconds * MICROSECS_PER_SEC; + int ret = oc_cond_wait_for(cv, mutex, wait_time); + oc_mutex_unlock(mutex); + return ret; +} + +static CAResult_t CALEGattConnectionRetry(const char *remoteAddress) +{ + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL_RET(remoteAddress, TAG, + "remote address is NULL", CA_STATUS_FAILED); + + CALEGattDisConnect(remoteAddress); + CALEWaittillDisconnect(g_isDisconnectedMutex, g_LEDisconnectedCond, 10); + CAResult_t result = CALEGattConnect(remoteAddress); + OIC_LOG(DEBUG, TAG, "OUT"); + return result; +} + CAResult_t CALEGattDiscoverServices(const char *remoteAddress) { OIC_LOG(DEBUG, TAG, "IN"); @@ -939,197 +1337,345 @@ CAResult_t CALEGattDiscoverServices(const char *remoteAddress) VERIFY_NON_NULL_RET(remoteAddress, TAG, "remote address is NULL", CA_STATUS_FAILED); - bt_gatt_client_h clientHandle = NULL; - int32_t ret = bt_gatt_client_create(remoteAddress, &clientHandle); - if (BT_ERROR_NONE != ret || NULL == clientHandle) + LEServerInfo *serverInfo = NULL; + unsigned int mtu_size; + oc_mutex_lock(g_LEServerListMutex); + if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo)) { - OIC_LOG_V(ERROR, TAG, - "bt_gatt_client_create Failed with ret value [%s] ", CALEGetErrorMsg(ret)); + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG_V(ERROR, TAG, "Could not get server info for [%s]", remoteAddress); CALEGattDisConnect(remoteAddress); return CA_STATUS_FAILED; } bt_gatt_h serviceHandle = NULL; - ret = bt_gatt_client_get_service(clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle); + int32_t ret = bt_gatt_client_get_service(serverInfo->clientHandle, CA_GATT_SERVICE_UUID, &serviceHandle); if (BT_ERROR_NONE != ret || NULL == serviceHandle) { 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; + + if(g_retrycount) + { + OIC_LOG(DEBUG, TAG, "Retry will be attempted to connect Gatt Server"); + g_retrycount--; + retry_flag = 1; + OIC_LOG_V(DEBUG, TAG, "Retry count left %d time(s)", g_retrycount); + CAResult_t result = CALEGattConnectionRetry(remoteAddress); + if(result == CA_STATUS_FAILED) + { + goto error_exit; + } + else + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Previous connection attempt failed, attempting to retry again"); + OIC_LOG_V(DEBUG, TAG, "Retry count left %d time(s)", g_retrycount); + return CA_STATUS_FAILED; + } + } } + retry_flag = 0; // Server will read data on this characteristic. bt_gatt_h writeChrHandle = NULL; ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_REQUEST_CHRC_UUID, - &writeChrHandle); + &writeChrHandle); if (BT_ERROR_NONE != ret || NULL == writeChrHandle) { OIC_LOG_V(ERROR, TAG, "bt_gatt_service_get_characteristic Failed with ret value [%s] ", CALEGetErrorMsg(ret)); - bt_gatt_client_destroy(clientHandle); - CALEGattDisConnect(remoteAddress); - return CA_STATUS_FAILED; + goto error_exit; } // Server will notify data on this characteristic. bt_gatt_h readChrHandle = NULL; ret = bt_gatt_service_get_characteristic(serviceHandle, CA_GATT_RESPONSE_CHRC_UUID, - &readChrHandle); + &readChrHandle); if (BT_ERROR_NONE != ret || NULL == readChrHandle) { OIC_LOG_V(ERROR, TAG, "bt_gatt_service_get_characteristic Failed with ret value [%s] ", CALEGetErrorMsg(ret)); - bt_gatt_client_destroy(clientHandle); - CALEGattDisConnect(remoteAddress); - return CA_STATUS_FAILED; + goto error_exit; } //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"); + goto error_exit; + } + ret = bt_gatt_client_set_characteristic_value_changed_cb(readChrHandle, - CALEGattCharacteristicChangedCb, - (void *)addr); + CALEGattCharacteristicChangedCb, + (void *)addr); if (BT_ERROR_NONE != ret) { OIC_LOG_V(ERROR, TAG, "bt_gatt_client_set_characteristic_value_changed_cb Failed with ret value [%s]", CALEGetErrorMsg(ret)); - bt_gatt_client_destroy(clientHandle); - CALEGattDisConnect(remoteAddress); - return CA_STATUS_FAILED; + goto error_exit; } - LEServerInfo *serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo)); - if (NULL == serverInfo) + ret = bt_gatt_client_set_att_mtu_changed_cb(serverInfo->clientHandle, + CALEGattClientMTUChangedCb, + (void *)serverInfo->remoteAddress); + if (BT_ERROR_NONE != ret) { - OIC_LOG(ERROR, TAG, "Malloc failed"); - CALEGattDisConnect(remoteAddress); - return CA_MEMORY_ALLOC_FAILED; + OIC_LOG_V(ERROR, TAG, + "bt_gatt_client_set_att_mtu_changed_cb Failed with ret value [%s]", + CALEGetErrorMsg(ret)); + goto error_exit; } - serverInfo->clientHandle = clientHandle; - serverInfo->serviceHandle = serviceHandle; - serverInfo->readChar = readChrHandle; - serverInfo->writeChar = writeChrHandle; - serverInfo->remoteAddress = OICStrdup(remoteAddress); - ca_mutex_lock(g_LEServerListMutex); - CAResult_t result = CAAddLEServerInfoToList(&g_LEServerList, serverInfo); - if (CA_STATUS_OK != result) + oc_mutex_lock(g_threadMTUChangedMutex); + ret = bt_gatt_client_request_att_mtu_change(serverInfo->clientHandle, CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_MTU_HEADER_SIZE); + if (BT_ERROR_NONE != ret) { - OIC_LOG(ERROR, TAG, "CAAddBLEClientInfoToList failed"); - bt_gatt_client_destroy(clientHandle); - CALEGattDisConnect(remoteAddress); - return CA_STATUS_FAILED; + OIC_LOG_V(ERROR, TAG, + "bt_gatt_client_request_att_mtu_change Failed with ret value [%s]", + CALEGetErrorMsg(ret)); + oc_mutex_unlock(g_threadMTUChangedMutex); + goto error_exit; } - ca_mutex_unlock(g_LEServerListMutex); - // Send the data of pending multicast data list if any. - if (g_multicastDataList) + OIC_LOG(DEBUG, TAG, "wait for callback to notify MTU Changed Callback"); + oc_cond_wait(g_threadMTUChangedCond, g_threadMTUChangedMutex); + oc_mutex_unlock(g_threadMTUChangedMutex); + + OIC_LOG(DEBUG, TAG, "Done MTU"); + ret = bt_gatt_client_get_att_mtu(serverInfo->clientHandle, &mtu_size); + if (BT_ERROR_NONE != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_client_get_att_mtu Failed with ret value [%s]", + CALEGetErrorMsg(ret)); + goto error_exit; + } + OIC_LOG_V(DEBUG, TAG,"Negotiated MTU Size %d",mtu_size); + + serverInfo->serviceHandle = serviceHandle; + serverInfo->readChar = readChrHandle; + serverInfo->writeChar = writeChrHandle; + serverInfo->status = LE_STATUS_SERVICES_DISCOVERED; + serverInfo->mtu_size = mtu_size; + + while (serverInfo->pendingDataList) { - ca_mutex_lock(g_multicastDataListMutex); - uint32_t arrayLength = u_arraylist_length(g_multicastDataList); - for (int i = 0; i < arrayLength; i++) + LEData *leData = serverInfo->pendingDataList->data; + if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl( + serverInfo, leData->data, leData->dataLength)) { - 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); + OIC_LOG_V(ERROR, TAG, "Failed to send pending data to [%s]", + serverInfo->remoteAddress); + + CADestroyLEDataList(&serverInfo->pendingDataList); + break; } - ca_mutex_unlock(g_multicastDataListMutex); + CARemoveLEDataFromList(&serverInfo->pendingDataList); } + oc_mutex_unlock(g_LEServerListMutex); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; + +error_exit: + bt_gatt_client_destroy(serverInfo->clientHandle); + serverInfo->clientHandle = NULL; + oc_mutex_unlock(g_LEServerListMutex); + CALEGattDisConnect(remoteAddress); + return CA_STATUS_FAILED; } -CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, - const uint8_t *data, const uint32_t dataLen, - CALETransferType_t type, const int32_t position) +CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, + const uint8_t *data, const uint32_t dataLen, + CALETransferType_t type, const int32_t position) { OIC_LOG(DEBUG, TAG, "IN"); VERIFY_NON_NULL(data, TAG, "data is NULL"); - if (0 >= dataLen) + if (0 == dataLen) { OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input!"); return CA_STATUS_INVALID_PARAM; } - LEServerInfo *leServerInfo = NULL; - CAResult_t ret = CA_STATUS_FAILED; - - ca_mutex_lock(g_LEServerListMutex); + LEServerInfo *serverInfo = NULL; + bool isConnected = false; + oc_mutex_lock(g_LEServerListMutex); if (LE_UNICAST == type) { - ret = CAGetLEServerInfo(g_LEServerList, remoteAddress, &leServerInfo); - } - else if (LE_MULTICAST == type) - { - ret = CAGetLEServerInfoByPosition(g_LEServerList, position, &leServerInfo); - } - ca_mutex_unlock(g_LEServerListMutex); + if (CA_STATUS_OK != CAGetLEServerInfo(g_LEServerList, remoteAddress, &serverInfo)) + { + OIC_LOG_V(DEBUG, TAG, + "Device with address [%s] not yet found, initiating scan", + remoteAddress); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, TAG, "CAGetBLEServiceInfoByPosition is failed"); - return CA_STATUS_FAILED; - } + char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Device address is NULL"); + return CA_STATUS_FAILED; + } + serverInfo = (LEServerInfo *)OICCalloc(1, sizeof(LEServerInfo)); + if (NULL == serverInfo) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Calloc failed"); + OICFree(addr); + return CA_STATUS_FAILED; + } + serverInfo->remoteAddress = addr; + serverInfo->status = LE_STATUS_UNICAST_PENDING; - VERIFY_NON_NULL(leServerInfo, TAG, "bleServiceInfo is NULL"); + if (CA_STATUS_OK != CAAddLEServerInfoToList(&g_LEServerList, serverInfo)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG_V(ERROR, TAG, "Could not add [%s] to server list", remoteAddress); + CAFreeLEServerInfo(serverInfo); + return CA_STATUS_FAILED; + } - OIC_LOG_V(DEBUG, TAG, "Updating the data of length [%d] to [%s] ", dataLen, - leServerInfo->remoteAddress); + if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Could not add data to pending list"); + return CA_STATUS_FAILED; + } + } - int result = bt_gatt_set_value(leServerInfo->writeChar, (char *)data, dataLen); + if(serverInfo->status == LE_STATUS_UNICAST_PENDING) + { - if (BT_ERROR_NONE != result) - { - OIC_LOG_V(ERROR, TAG, - "bt_gatt_set_value Failed with return val [%s]", - CALEGetErrorMsg(result)); - return CA_STATUS_FAILED; - } + int ret = bt_device_is_profile_connected(remoteAddress, BT_PROFILE_GATT, &isConnected); + if (BT_ERROR_NONE != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_device_is_profile_connected Failed with ret value [%s] ", + CALEGetErrorMsg(ret)); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } - result = bt_gatt_client_write_value(leServerInfo->writeChar, CALEGattCharacteristicWriteCb, - NULL); - if (BT_ERROR_NONE != result) - { - OIC_LOG_V(ERROR, TAG, - "bt_gatt_client_write_value Failed with return val [%s]", - CALEGetErrorMsg(result)); - return CA_STATUS_FAILED; - } + if (isConnected){ + OIC_LOG_V(DEBUG, TAG, "Already connected to address [%s]", remoteAddress); + serverInfo->status = LE_STATUS_CONNECTED; + } else { + oc_mutex_lock(g_scanMutex); + if (!g_isMulticastInProgress && !g_isUnicastScanInProgress) + { + CAResult_t result = CALEGattStartDeviceScanning(); + if (CA_STATUS_OK != result) + { + oc_mutex_unlock(g_scanMutex); + OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning failed"); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + g_isUnicastScanInProgress = true; + // Start Timer + oc_cond_signal(g_startTimerCond); + } + else + { + g_isUnicastScanInProgress = true; + // Reset Timer + oc_cond_signal(g_scanningTimeCond); + } + oc_mutex_unlock(g_scanMutex); + } - // wait for callback for write Characteristic with success to sent data - OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag); - ca_mutex_lock(g_threadWriteCharacteristicMutex); - if (!g_isSignalSetFlag) - { - OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success"); - if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond, - g_threadWriteCharacteristicMutex, - WAIT_TIME_WRITE_CHARACTERISTIC)) + } + + if (serverInfo->status == LE_STATUS_CONNECTED) { - OIC_LOG(ERROR, TAG, "there is no response. write has failed"); - g_isSignalSetFlag = false; - ca_mutex_unlock(g_threadWriteCharacteristicMutex); - return CA_SEND_FAILED; + oc_mutex_lock(g_LEClientThreadPoolMutex); + if (NULL == g_LEClientThreadPool) + { + oc_mutex_unlock(g_LEClientThreadPoolMutex); + OIC_LOG(ERROR, TAG, "g_LEClientThreadPool is NULL"); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + char *addr = OICStrdup(remoteAddress); + if (NULL == addr) + { + oc_mutex_unlock(g_LEClientThreadPoolMutex); + OIC_LOG(ERROR, TAG, "addr is NULL"); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + CAResult_t ret = ca_thread_pool_add_task(g_LEClientThreadPool, CADiscoverLEServicesThread, + addr, NULL); + oc_mutex_unlock(g_LEClientThreadPoolMutex); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret); + OICFree(addr); + } } - } - // reset flag set by writeCharacteristic Callback - g_isSignalSetFlag = false; - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + if (serverInfo->status == LE_STATUS_DISCOVERED) + { + if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Could not add data to pending list"); + return CA_STATUS_FAILED; + } + + bt_gatt_client_h clientHandle = NULL; + int32_t ret = bt_gatt_client_create(serverInfo->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(serverInfo->remoteAddress); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + serverInfo->clientHandle = clientHandle; + + serverInfo->status = LE_STATUS_CONNECTION_INITIATED; + if (CA_STATUS_OK != CALEGattInitiateConnection(serverInfo->remoteAddress)) + { + OIC_LOG_V(ERROR, TAG, "Could not initiate connection to [%s]", serverInfo->remoteAddress); + serverInfo->status = LE_STATUS_DISCOVERED; + CADestroyLEDataList(&serverInfo->pendingDataList); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + } + else if (serverInfo->status < LE_STATUS_SERVICES_DISCOVERED) + { + if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen)) + { + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG(ERROR, TAG, "Could not add data to pending list"); + return CA_STATUS_FAILED; + } + } + else + { + if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen)) + { + OIC_LOG_V(ERROR, TAG, "Could not update characteristic to gatt server [%s]", + serverInfo->remoteAddress); + oc_mutex_unlock(g_LEServerListMutex); + return CA_STATUS_FAILED; + } + } + } + else if (LE_MULTICAST == type) + { + OIC_LOG(ERROR, TAG, "LE_MULTICAST type Not used"); + } + oc_mutex_unlock(g_LEServerListMutex); OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } @@ -1140,32 +1686,38 @@ CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t VERIFY_NON_NULL(data, TAG, "data is NULL"); - if (0 >= dataLen) + if (0 == dataLen) { OIC_LOG(ERROR, TAG, "dataLen is less than or equal zero. Invalid input !"); return CA_STATUS_INVALID_PARAM; } - int numOfServersConnected = CAGetRegisteredServiceCount(); - - // Send data to already connected devices. - for (int32_t pos = 0; pos < numOfServersConnected; pos++) + oc_mutex_lock(g_LEServerListMutex); + LEServerInfoList *curNode = g_LEServerList; + while (curNode) { - /*remoteAddress will be NULL. - Since we have to send to all destinations. pos will be used for getting remote address. - */ - int32_t ret = CAUpdateCharacteristicsToGattServer(NULL, data, dataLen, LE_MULTICAST, pos); - - if (CA_STATUS_OK != ret) + LEServerInfo *serverInfo = curNode->serverInfo; + if (serverInfo->status == LE_STATUS_SERVICES_DISCOVERED) + { + if (CA_STATUS_OK != CAUpdateCharacteristicsToGattServerImpl(serverInfo, data, dataLen)) + { + OIC_LOG_V(ERROR, TAG, "Failed to update characteristics to gatt server [%s]", + serverInfo->remoteAddress); + } + } + else if (serverInfo->status != LE_STATUS_INVALID) { - OIC_LOG_V(ERROR, TAG, - "CAUpdateCharacteristicsToGattServer Failed with return val [%d] ", ret); - g_clientErrorCallback(NULL, data, dataLen, ret); + if (CA_STATUS_OK != CAAddLEDataToList(&serverInfo->pendingDataList, data, dataLen)) + { + OIC_LOG(ERROR, TAG, "Failed to add to pending list"); + } } + curNode = curNode->next; } + oc_mutex_unlock(g_LEServerListMutex); // Add the data to pending list. - CALEData_t *multicastData = (CALEData_t *)OICCalloc(1, sizeof(CALEData_t)); + LEData *multicastData = (LEData *)OICCalloc(1, sizeof(LEData)); if (NULL == multicastData) { OIC_LOG(ERROR, TAG, "Calloc failed"); @@ -1178,30 +1730,83 @@ CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t goto exit; } memcpy(multicastData->data, data, dataLen); - multicastData->dataLen = dataLen; + multicastData->dataLength = 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(); - if (CA_STATUS_OK != result) + // Start the scanning, if not started, else reset timer + oc_mutex_lock(g_scanMutex); + if (!g_isMulticastInProgress && !g_isUnicastScanInProgress) { - OIC_LOG(ERROR, TAG, "CALEGattStartDeviceDiscovery Failed"); - goto exit; + CAResult_t result = CALEGattStartDeviceScanning(); + if (CA_STATUS_OK != result) + { + oc_mutex_unlock(g_scanMutex); + OIC_LOG(ERROR, TAG, "CALEGattStartDeviceScanning Failed"); + goto exit; + } + g_isMulticastInProgress = true; + // Start the timer by signalling it + oc_cond_signal(g_startTimerCond); } - - // Start the timer by signalling it. - ca_cond_signal(g_startTimerCond); + else + { + g_isMulticastInProgress = true; + // Reset timer + oc_cond_signal(g_scanningTimeCond); + } + oc_mutex_unlock(g_scanMutex); exit: OIC_LOG(DEBUG, TAG, "OUT "); return CA_STATUS_OK; } +uint16_t CALEClientGetMtuSize(const char* remote_address) +{ + LEServerInfo *serverInfo = NULL; + oc_mutex_lock(g_LEServerListMutex); + if (CA_STATUS_OK == CAGetLEServerInfo(g_LEServerList, remote_address, &serverInfo)) + { + if (serverInfo->status == LE_STATUS_SERVICES_DISCOVERED){ + OIC_LOG_V(DEBUG, TAG, "Mtu Size [%d]", serverInfo->mtu_size); + oc_mutex_unlock(g_LEServerListMutex); + OIC_LOG_V(INFO, TAG, "Returning Mtu Size [%d]", serverInfo->mtu_size - CA_BLE_MTU_HEADER_SIZE); + return serverInfo->mtu_size - CA_BLE_MTU_HEADER_SIZE; + } + } + oc_mutex_unlock(g_LEServerListMutex); + return CA_DEFAULT_BLE_MTU_SIZE; + +} + +bool CALEClientIsConnected(const char* address) +{ + (void)address; + //@Todo + return true; +} + +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; +}