From 0b241948e3b5d0abd84cea98c3ccfe7b3defaf88 Mon Sep 17 00:00:00 2001 From: "vimala.v" Date: Mon, 1 Feb 2016 10:35:31 +0530 Subject: [PATCH] BLE Server support for Tizen 2.4 Change-Id: Id85ef1b321d428780a47d07f76433d3a6884b27a Signed-off-by: koushik.girijala Signed-off-by: jihwan.seo Signed-off-by: vimala.v Signed-off-by: jihwan.seo Signed-off-by: vimala.v Reviewed-on: https://gerrit.iotivity.org/gerrit/4859 Tested-by: jenkins-iotivity Reviewed-by: Jaehong Jo Reviewed-by: Jon A. Cruz --- .../src/bt_le_adapter/tizen/caleserver.c | 855 +++++++++++++++++++-- .../src/bt_le_adapter/tizen/caleserver.h | 127 +-- 2 files changed, 815 insertions(+), 167 deletions(-) diff --git a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c index 1e2b594..f38284f 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c @@ -20,173 +20,870 @@ #include #include +#include #include "caleserver.h" -#include #include "cacommon.h" -#include "caadapterutils.h" -#include +#include "cacommonutil.h" #include "camutex.h" #include "caqueueingthread.h" -#include "caadapterutils.h" -#include "cafragmentation.h" #include "cagattservice.h" -#include "caleutil.h" -#include "oic_string.h" #include "oic_malloc.h" +#include "caleutil.h" + +/** + * Logging tag for module name + */ +#define TAG "OIC_CA_LE_SERVER" + +/** + * Initial buffer size for Gatt Server. + */ +#define CA_LE_INITIAL_BUF_SIZE 512 + +/** + * The handle of the OIC server. + */ +static bt_gatt_server_h g_gattServer = NULL; + +/** + * The handle of the OIC service. + */ +static bt_gatt_h g_gattSvcPath = NULL; + +/** + * The handle of the OIC read characteristics. + */ +static bt_gatt_h g_gattReadCharPath = NULL; + +/** + * The handle of the OIC write characteristics. + */ +static bt_gatt_h g_gattWriteCharPath = NULL; + +/** + * The handle to control Bluetooth LE advertising. + */ +static bt_advertiser_h g_hAdvertiser = NULL; + +/** + * Callback register with LE adapter. This callback is called on reception of any + * data from the remote device. + */ +static CABLEDataReceivedCallback g_leServerDataReceivedCallback = NULL; /** - * @def TZ_BLE_SERVER_TAG - * @brief Logging tag for module name + * Callback to notify any error in LE adapter. */ -#define TZ_BLE_SERVER_TAG "OIC_CA_LE_SERVER" +static CABLEErrorHandleCallback g_serverErrorCallback; -void CABleGattServerConnectionStateChangedCb(int result, bool connected, - const char *remoteAddress, void *userData) +/** + * To keep the state of GATT server if started or not. + */ +static bool g_isLEGattServerStarted = false; + +/** + * Mutex to synchronize the calls to start and stop server. + */ +static ca_mutex g_leServerStateMutex = NULL; + +/** + * Mutex to synchronize writing operations on the characteristics. + */ +static ca_mutex g_leCharacteristicMutex = NULL; + +/** + * Mutex to synchronize to creation of OIC service. + */ +static ca_mutex g_leServiceMutex = 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_leReqRespCbMutex = NULL; + +/** + * Mutex to synchronize the task to be pushed to thread pool. + */ +static ca_mutex g_leServerThreadPoolMutex = NULL; + +/** + * Reference to threadpool. + */ +static ca_thread_pool_t g_leServerThreadPool = NULL; + +/** + * GmainLoop to manage the threads to receive the callback from the platfrom. + */ +static GMainLoop *g_eventLoop = NULL; + +void CALEGattServerConnectionStateChangedCb(int result, bool connected, + const char *remoteAddress, void *userData) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL_VOID(remoteAddress, TAG, "remote address"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG_V(DEBUG, TAG, "CABleGattConnectionStateChangedCb result[%d]", result); + + if (connected) + { + OIC_LOG_V(DEBUG, TAG, "Connected to [%s]", remoteAddress); + } + OIC_LOG(DEBUG, TAG, "OUT"); +} + +void CALEServerNotificationSentCB(int result, char *remote_address, bt_gatt_server_h server, + bt_gatt_h characteristic, bool completed, void *user_data) +{ + OIC_LOG_V(DEBUG, TAG, "Notification to the device[%s] result[%d]", remote_address, result); } CAResult_t CAStartLEGattServer() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + ca_mutex_lock(g_leServerThreadPoolMutex); + if (NULL == g_leServerThreadPool) + { + OIC_LOG(ERROR, TAG, "g_leServerThreadPool is NULL"); + ca_mutex_unlock(g_leServerThreadPoolMutex); + return CA_STATUS_FAILED; + } + + CAResult_t ret = ca_thread_pool_add_task(g_leServerThreadPool, CAStartLEGattServerThread, + NULL); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "ca_thread_pool_add_task failed with ret [%d]", ret); + ca_mutex_unlock(g_leServerThreadPoolMutex); + return CA_STATUS_FAILED; + } + + ca_mutex_unlock(g_leServerThreadPoolMutex); + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -void CAStartBleGattServerThread(void *data) +void CALENotificationCb(bool notify, bt_gatt_server_h server, bt_gatt_h gatt_handle, + void *user_data) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + if(notify) + { + OIC_LOG(DEBUG, TAG, "Notification is subscribed by the client"); + } + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAStopLEGattServer() +CAResult_t CALEStartAdvertise(const char *serviceUUID) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + + int res = bt_adapter_le_create_advertiser(&g_hAdvertiser); + if (NULL == g_hAdvertiser || BT_ERROR_NONE != res) + { + OIC_LOG_V(ERROR, TAG, "g_hAdvertiser is NULL/ Result is %d", res); + return CA_STATUS_FAILED; + } + + res = bt_adapter_le_add_advertising_service_uuid(g_hAdvertiser, + BT_ADAPTER_LE_PACKET_ADVERTISING, + serviceUUID); + if (BT_ERROR_NONE != res) + { + OIC_LOG_V(ERROR, TAG, "bt_adapter_le_add_advertising_service_uuid failed with ret[%s]", + CALEGetErrorMsg(res)); + return CA_STATUS_FAILED; + } + + res = bt_adapter_le_start_advertising(g_hAdvertiser, NULL, NULL, NULL); + if (BT_ERROR_NONE != res) + { + OIC_LOG_V(ERROR, TAG, "bt_adapter_le_start_advertising failed with ret[%s]", + CALEGetErrorMsg(res)); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; +} - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); +CAResult_t CALEStopAdvertise() +{ + OIC_LOG(DEBUG, TAG, "IN"); + if (NULL != g_hAdvertiser) + { + int ret = bt_adapter_le_stop_advertising(g_hAdvertiser); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_adapter_le_stop_advertising failed with ret[%s]", CALEGetErrorMsg(ret)); + } + + ret = bt_adapter_le_destroy_advertiser(g_hAdvertiser); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_adapter_le_destroy_advertiser failed with ret[%s]", CALEGetErrorMsg(ret)); + } + g_hAdvertiser = NULL; + } + else + { + OIC_LOG(ERROR, TAG, "Advertising is not running"); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -void CATerminateLEGattServer() +void CAStartLEGattServerThread(void *data) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + ca_mutex_lock(g_leServerStateMutex); + if (true == g_isLEGattServerStarted) + { + OIC_LOG(ERROR, TAG, "Gatt Server is already running"); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + CAResult_t ret = CAInitLEGattServer(); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "CAInitLEGattService failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + char *serviceUUID = CA_GATT_SERVICE_UUID; + + ret = CAAddNewLEServiceInGattServer(serviceUUID); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "CAAddNewLEServiceInGattServer failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + static const char charReadUUID[] = CA_GATT_RESPONSE_CHRC_UUID; + char charReadValue[] = {33, 44, 55, 66}; // These are initial random values + + // For Read Characteristics. + ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charReadUUID, charReadValue, + CA_LE_INITIAL_BUF_SIZE, true); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + static const char charWriteUUID[] = CA_GATT_REQUEST_CHRC_UUID; + char charWriteValue[] = {33, 44, 55, 66}; // These are initial random values + + + ret = CAAddNewCharacteristicsToGattServer(g_gattSvcPath, charWriteUUID, charWriteValue, + CA_LE_INITIAL_BUF_SIZE, false); // For Write Characteristics. + if (CA_STATUS_OK != ret ) + { + OIC_LOG_V(ERROR, TAG, "CAAddNewCharacteristicsToGattServer failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + ret = CARegisterLEServicewithGattServer(g_gattSvcPath); + if (CA_STATUS_OK != ret ) + { + OIC_LOG_V(ERROR, TAG, "CARegisterLEServicewithGattServer failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + int res = bt_gatt_set_connection_state_changed_cb(CALEGattServerConnectionStateChangedCb, + NULL); + if (BT_ERROR_NONE != res) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_set_connection_state_changed_cb Failed with return as [%s]", + CALEGetErrorMsg(res)); + return; + } + + ret = CALEStartAdvertise(serviceUUID); + if (CA_STATUS_OK != ret) + { + OIC_LOG_V(ERROR, TAG, "CALEStartAdvertise failed[%d]", ret); + ca_mutex_unlock(g_leServerStateMutex); + CATerminateLEGattServer(); + return; + } + + g_isLEGattServerStarted = true; + + ca_mutex_unlock(g_leServerStateMutex); + + OIC_LOG(DEBUG, TAG, "LE Server initialization complete."); + + GMainContext *thread_context = NULL; + + 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); + + OIC_LOG(DEBUG, TAG, "OUT"); +} - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); +CAResult_t CAStopLEGattServer() +{ + OIC_LOG(DEBUG, TAG, "IN"); + + ca_mutex_lock(g_leServerStateMutex); + + if (false == g_isLEGattServerStarted) + { + OIC_LOG(ERROR, TAG, "Gatt Server is not running to stop"); + ca_mutex_unlock(g_leServerStateMutex); + return CA_STATUS_OK; + } + + g_isLEGattServerStarted = false; + + CAResult_t res = CALEStopAdvertise(); + { + OIC_LOG_V(ERROR, TAG, "CALEStopAdvertise failed with ret[%d]", res); + } + + res = CADeInitLEGattServer(); + if (CA_STATUS_OK != res) + { + OIC_LOG_V(ERROR, TAG, "CADeInitLEGattService failed with ret[%d]", res); + } + + GMainContext *context_event_loop = NULL; + // Required for waking up the thread which is running in gmain loop + if (NULL != g_eventLoop) + { + context_event_loop = g_main_loop_get_context(g_eventLoop); + + if (context_event_loop) + { + OIC_LOG_V(DEBUG, TAG, "g_eventLoop context %x", context_event_loop); + g_main_context_wakeup(context_event_loop); + + // Kill g main loops and kill threads + g_main_loop_quit(g_eventLoop); + } + } + else + { + OIC_LOG(ERROR, TAG, "g_eventLoop context is NULL"); + } + + ca_mutex_unlock(g_leServerStateMutex); + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } CAResult_t CAInitializeLEGattServer() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, TAG, "IN"); + + CAResult_t ret = CAInitGattServerMutexVariables(); + if (CA_STATUS_OK != ret ) + { + OIC_LOG(ERROR, TAG, "CAInitGattServerMutexVariables failed!"); + CATerminateGattServerMutexVariables(); + return CA_SERVER_NOT_STARTED; + } + OIC_LOG(DEBUG, TAG, "OUT"); + return ret; } -CAResult_t CAInitBleGattService() +void CATerminateLEGattServer() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + // Service and characteristics path will be freed by the platform. + ca_mutex_lock(g_leServiceMutex); + g_gattSvcPath = NULL; + ca_mutex_unlock(g_leServiceMutex); + + ca_mutex_lock(g_leCharacteristicMutex); + g_gattReadCharPath = NULL; + g_gattWriteCharPath = NULL; + ca_mutex_unlock(g_leCharacteristicMutex); + + ca_mutex_lock(g_leServerThreadPoolMutex); + g_leServerThreadPool = NULL; + ca_mutex_unlock(g_leServerThreadPoolMutex); + + // Terminating all mutex variables. + CATerminateGattServerMutexVariables(); + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CADeInitBleGattService() +CAResult_t CAInitGattServerMutexVariables() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + if (NULL == g_leServerStateMutex) + { + g_leServerStateMutex = ca_mutex_new(); + if (NULL == g_leServerStateMutex) + { + OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_leServiceMutex) + { + g_leServiceMutex = ca_mutex_new(); + if (NULL == g_leServiceMutex) + { + OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_leCharacteristicMutex) + { + g_leCharacteristicMutex = ca_mutex_new(); + if (NULL == g_leCharacteristicMutex) + { + OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_leReqRespCbMutex) + { + g_leReqRespCbMutex = ca_mutex_new(); + if (NULL == g_leReqRespCbMutex) + { + OIC_LOG(ERROR, TAG, "ca_mutex_new failed"); + return CA_STATUS_FAILED; + } + } + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle) +void CATerminateGattServerMutexVariables() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + ca_mutex_free(g_leServerStateMutex); + g_leServerStateMutex = NULL; + + ca_mutex_free(g_leServiceMutex); + g_leServiceMutex = NULL; + + ca_mutex_free(g_leCharacteristicMutex); + g_leCharacteristicMutex = NULL; + + ca_mutex_free(g_leReqRespCbMutex); + g_leReqRespCbMutex = NULL; + + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAAddNewBleServiceInGattServer(const char *serviceUUID) +CAResult_t CAInitLEGattServer() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + int ret = bt_gatt_server_initialize(); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_initialize failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + bt_gatt_server_h server; + + ret = bt_gatt_server_create(&server); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_create failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + if (NULL != g_gattServer) + { + OICFree(g_gattServer); + g_gattServer = NULL; + } + g_gattServer = server; + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CARemoveBleServiceFromGattServer(const char *svcPath) +CAResult_t CADeInitLEGattServer() { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + int ret = bt_gatt_server_unregister_all_services(g_gattServer); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_unregister_all_services failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_server_destroy(g_gattServer); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_destroy failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_server_deinitialize(); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_deinitialize failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CARemoveAllBleServicesFromGattServer() +void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, TAG, "IN"); + ca_mutex_lock(g_leServerThreadPoolMutex); + g_leServerThreadPool = handle; + ca_mutex_unlock(g_leServerThreadPoolMutex); + OIC_LOG(DEBUG, TAG, "OUT"); } -void CABleGattRemoteCharacteristicWriteCb(char *charPath, - unsigned char *charValue, - int charValueLen, - const char *remoteAddress, - void *userData) +CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(serviceUUID, TAG, "serviceUUID"); + + OIC_LOG_V(DEBUG, TAG, "service uuid %s", serviceUUID); + + bt_gatt_h service = NULL; + bt_gatt_service_type_e type = BT_GATT_SERVICE_TYPE_PRIMARY; + + int ret = bt_gatt_service_create(serviceUUID, type, &service); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_service_create failed with ret [%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + if (NULL != service) + { + OIC_LOG_V(DEBUG, TAG, "ServicePath obtained is %s", (char *)service); + + ca_mutex_lock(g_leServiceMutex); + + if (NULL != g_gattSvcPath) + { + OICFree(g_gattSvcPath); + g_gattSvcPath = NULL; + } + g_gattSvcPath = service; + + ca_mutex_unlock(g_leServiceMutex); + } + + OIC_LOG(DEBUG, TAG, "OUT"); + return CA_STATUS_OK; } -CAResult_t CARegisterBleServicewithGattServer(const char *svcPath) +void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server, + bt_gatt_h charPath, int offset, char *charValue, + int charValueLen, void *userData) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); - return CA_STATUS_OK; + OIC_LOG(DEBUG, TAG, "IN"); + + if (NULL == charValue || NULL == remoteAddress) + { + OIC_LOG(ERROR, TAG, "Param callback values are NULL"); + return; + } + + OIC_LOG_V(DEBUG, TAG, "charPath = [%s] charValue = [%s] len [%d]", (char *)charPath, + charValue, charValueLen); + + uint8_t *data = OICMalloc(charValueLen); + if (NULL == data) + { + OIC_LOG(ERROR, TAG, "Malloc failed!"); + return; + } + + memcpy(data, charValue, charValueLen); + + ca_mutex_lock(g_leReqRespCbMutex); + if (NULL == g_leServerDataReceivedCallback) + { + OIC_LOG(ERROR, TAG, "gReqRespCallback is NULL!"); + ca_mutex_unlock(g_leReqRespCbMutex); + OICFree(data); + return; + } + + OIC_LOG(DEBUG, TAG, "Sending data up !"); + uint32_t sentLength = 0; + g_leServerDataReceivedCallback(remoteAddress, data, charValueLen, + &sentLength); + ca_mutex_unlock(g_leReqRespCbMutex); + OICFree(data); + OIC_LOG(DEBUG, TAG, "OUT"); } -CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char *charUUID, - const uint8_t *charValue, int charValueLen, bool read) +CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath) { + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(svcPath, TAG, "svcPath"); + + OIC_LOG_V(DEBUG, TAG, "svcPath:%s", svcPath); + + int ret = bt_gatt_server_register_service(g_gattServer, svcPath); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_register_service failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_server_set_value_changed_cb(g_gattWriteCharPath, + CALEGattRemoteCharacteristicWriteCb, NULL); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_server_set_value_changed_cb failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CARemoveCharacteristicsFromGattServer(const char *charPath) +CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID, + const char *charValue, int charValueLen, bool read) { - ///TODO: There is no api provided in bluetooth.h for removing characteristics. + + OIC_LOG(DEBUG, TAG, "IN"); + + int permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE; + int properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_NOTIFY; + if(read) + { + properties = BT_GATT_PROPERTY_NOTIFY | BT_GATT_PROPERTY_READ; + } + else + { + properties = BT_GATT_PROPERTY_WRITE | BT_GATT_PROPERTY_READ; + } + + bt_gatt_h charPath; + + int ret = bt_gatt_characteristic_create(charUUID, permissions, properties, charValue, + charValueLen, &charPath); + + if (0 != ret || NULL == charPath) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_add_characteristic failed with ret [%s]", CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + OIC_LOG_V(DEBUG, TAG, + "bt_gatt_characteristic_create charPath obtained: %s", (char *)charPath); + + if (read) + { + ret = bt_gatt_server_set_notification_state_change_cb(charPath, CALENotificationCb, NULL); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_server_set_notification_state_change_cb failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + } + + ret = bt_gatt_service_add_characteristic(svcPath, charPath); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_service_add_characteristic failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + ca_mutex_lock(g_leCharacteristicMutex); + + if (read) + { + char desc_value[2] = {1, 0}; // Notification enabled. + bt_gatt_h descriptor = NULL; + permissions = BT_GATT_PERMISSION_READ | BT_GATT_PERMISSION_WRITE; + ret = bt_gatt_descriptor_create(CA_GATT_CONFIGURATION_DESC_UUID, + permissions, desc_value, sizeof(desc_value), &descriptor); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_descriptor_create failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_characteristic_add_descriptor(charPath, descriptor); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_characteristic_add_descriptor failed with ret[%s]", + CALEGetErrorMsg(ret)); + return CA_STATUS_FAILED; + } + + if (NULL != g_gattReadCharPath) + { + OICFree(g_gattReadCharPath); + g_gattReadCharPath = NULL; + } + g_gattReadCharPath = charPath; + + } + else + { + if (NULL != g_gattWriteCharPath) + { + OICFree(g_gattWriteCharPath); + g_gattWriteCharPath = NULL; + } + g_gattWriteCharPath = charPath; + } + + ca_mutex_unlock(g_leCharacteristicMutex); + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } -CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, - const uint8_t *charValue, +CAResult_t CAUpdateCharacteristicsToGattClient(const char *address, const uint8_t *charValue, uint32_t charValueLen) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - - OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(charValue, TAG, "charValue"); + VERIFY_NON_NULL(address, TAG, "address"); + + OIC_LOG_V(DEBUG, TAG, "Client's Unicast address for sending data [%s]", address); + + ca_mutex_lock(g_leCharacteristicMutex); + + if (NULL == g_gattReadCharPath) + { + OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL"); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_set_value failed with return [%s]", CALEGetErrorMsg(ret)); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB, + address, NULL); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_server_notify failed with return [%s]", CALEGetErrorMsg(ret)); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + ca_mutex_unlock(g_leCharacteristicMutex); + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *charValue, uint32_t charValueLen) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); - - OIC_LOG(ERROR, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "IN"); + + VERIFY_NON_NULL(charValue, TAG, "charValue"); + + ca_mutex_lock(g_leCharacteristicMutex); + + if (NULL == g_gattReadCharPath) + { + OIC_LOG(ERROR, TAG, "g_gattReadCharPath is NULL"); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + int ret = bt_gatt_set_value(g_gattReadCharPath, (char *)charValue, charValueLen); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, "bt_gatt_set_value failed with return[%s]", CALEGetErrorMsg(ret)); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + ret = bt_gatt_server_notify(g_gattReadCharPath, false, CALEServerNotificationSentCB, + NULL, NULL); + if (0 != ret) + { + OIC_LOG_V(ERROR, TAG, + "bt_gatt_server_notify failed with return[%s]", CALEGetErrorMsg(ret)); + ca_mutex_unlock(g_leCharacteristicMutex); + return CA_STATUS_FAILED; + } + + ca_mutex_unlock(g_leCharacteristicMutex); + + OIC_LOG(DEBUG, TAG, "OUT"); return CA_STATUS_OK; } void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback) { - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "IN"); + OIC_LOG(DEBUG, TAG, "IN"); + + ca_mutex_lock(g_leReqRespCbMutex); + g_leServerDataReceivedCallback = callback; + ca_mutex_unlock(g_leReqRespCbMutex); - OIC_LOG(DEBUG, TZ_BLE_SERVER_TAG, "OUT"); + OIC_LOG(DEBUG, TAG, "OUT"); } void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback) { - + g_serverErrorCallback = callback; } diff --git a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h index f8bd414..4760d4e 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h +++ b/resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h @@ -38,32 +38,32 @@ /** * This is thread which will be used for creating ble service and advertise ble service. - * 1. Create New OIC Service 2. Add two read & write characteristics to service. - * 3. Register Service 4. Advertise service. + * 1. Create New OIC Service 2. Add read & write characteristics to service. + * 3. Register Service 4. Advertise service. * * @param[in] data Currently it will be NULL. */ -void CAStartBleGattServerThread(void *data); +void CAStartLEGattServerThread(void *data); /** - * Used to initialize gatt service using _bt_gatt_init_service api. + * Used to initialize gatt server. * * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CAInitBleGattService(); +CAResult_t CAInitLEGattServer(); /** - * Used to de-initialize gatt service using _bt_gatt_deinit_service api. + * Used to de-initialize gatt service and destroy the GATT server. * * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CADeInitBleGattService(); +CAResult_t CADeInitLEGattServer(); /** * Used to initialize all required mutex variables for GATT server implementation. @@ -75,58 +75,55 @@ CAResult_t CADeInitBleGattService(); */ CAResult_t CAInitGattServerMutexVariables(); - /** - * Used to terminate all required mutex variables for GATT server implementation. - */ -void CATerminateGattServerMutexVariables(); - -/** - * Used to add new OIC service in GATT server using bt_gatt_add_service api and - * internally store service path(outparam) in global variable. - * - * @param[in] serviceUUID unique identifier for BLE OIC service. + * Used to start advertising. * * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CAAddNewBleServiceInGattServer(const char *serviceUUID); +CAResult_t CALEStartAdvertise(const char *serviceUUID); /** - * Used to remove already registered service from Gatt Server using - * bt_gatt_remove_service api. - * @param[in] svcPath unique identifier for BLE OIC service which is outparam of - * bt_gatt_add_service api. + * Used to stop advertising. + * * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CARemoveBleServiceFromGattServer(const char *svcPath); +CAResult_t CALEStopAdvertise(); /** - * Used to remove all the registered service from Gatt Server using - * bt_gatt_delete_services api. + * Used to terminate all required mutex variables for GATT server implementation. + */ +void CATerminateGattServerMutexVariables(); + +/** + * Used to add new OIC service in GATT server using bt_gatt_add_service api and + * internally store service path(outparam) in global variable. + * + * @param[in] serviceUUID unique identifier for BLE OIC service. + * * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CARemoveAllBleServicesFromGattServer(); +CAResult_t CAAddNewLEServiceInGattServer(const char *serviceUUID); /** * Used to register the service in Gatt Server using bt_gatt_register_service api. * * @param[in] svcPath unique identifier for BLE OIC service which is outparam of - * bt_gatt_add_service api. + * bt_gatt_service_create api. * @return ::CA_STATUS_OK or Appropriate error code. * @retval ::CA_STATUS_OK Successful. * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. * @retval ::CA_STATUS_FAILED Operation failed. */ -CAResult_t CARegisterBleServicewithGattServer(const char *svcPath); +CAResult_t CARegisterLEServicewithGattServer(const bt_gatt_h svcPath); /** * Used to add new characteristics(Read/Write) to the service in Gatt Server using @@ -139,37 +136,23 @@ CAResult_t CARegisterBleServicewithGattServer(const char *svcPath); * write characteristics. * @return ::CA_STATUS_OK or Appropriate error code. */ -CAResult_t CAAddNewCharacteristicsToGattServer(const char *svcPath, const char *charUUID, - const uint8_t *charValue, int charValueLen, - bool read); - -/** - * Used to remove characteristics(Read/Write) from the service in Gatt Server. - * - * @param[in] charPath Characteristic path registered on the interface and unique identifier - * for added characteristics. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -CAResult_t CARemoveCharacteristicsFromGattServer(const char *charPath); +CAResult_t CAAddNewCharacteristicsToGattServer(const bt_gatt_h svcPath, const char *charUUID, + const char *charValue, int charValueLen, bool read); /** * This is the callback which will be called when client update one of the characteristics * with data. - * @param[in] charPath characteristic path registered on the interface and unique - * identifier for added characteristics. - * @param[in] charValue data which is send by client. - * @param[in] charValueLen length of the data. - * @param[in] remoteAddress remote device bluetooth address in which data is received. - * @param[in] userData user data. - + * @param[in] remote_address The address of the remote device which requests a change + * @param[in] server The GATT server handle + * @param[in] gatt_handle The characteristic or descriptor's GATT handle which has an old value + * @param[in] offset The requested offset from where the @a gatt_handle value will be updated + * @param[in] value The new value + * @param[in] len The length of @a value + * @param[in] user_data The user data passed from the registration function */ -void CABleGattRemoteCharacteristicWriteCb(char *charPath, unsigned char *charValue, - int charValueLen, const char *remoteAddress, - void *userData); +void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h server, + bt_gatt_h charPath, int offset, char *charValue, + int charValueLen, void *userData); /** * This is the callback which will be called whenever there is change in gatt connection @@ -179,41 +162,9 @@ void CABleGattRemoteCharacteristicWriteCb(char *charPath, unsigned char *charVal * @param[in] connected State of connection. * @param[in] remoteAddress Mac address of the remote device in which we made connection. * @param[in] userData The user data passed from the request function. - - */ -void CABleGattServerConnectionStateChangedCb(int result, bool connected, - const char *remoteAddress, void *userData); - -/** - * Synchronous function for reading characteristic value. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -CAResult_t CALEReadDataFromLEServer(); - -/** - * Used to enqueue the message into sender queue using CAAdapterEnqueueMessage and make - * signal to the thread to process. - * - * @param[in] remoteEndpoint Remote device information. - * @param[in] data Data to be sent to remote device. - * @param[in] dataLen Length of data. - * - * @return ::CA_STATUS_OK or Appropriate error code. - * @retval ::CA_STATUS_OK Successful. - * @retval ::CA_STATUS_INVALID_PARAM Invalid input arguments. - * @retval ::CA_STATUS_FAILED Operation failed. - */ -CAResult_t CABleServerSenderQueueEnqueueMessage - (const CAEndpoint_t *remoteEndpoint, const uint8_t *data, uint32_t dataLen); - -/** - * This is the thread which will be used for processing receiver queue. */ -void *CABleServerSenderQueueProcessor(); +void CALEGattServerConnectionStateChangedCb(int result, bool connected, + const char *remoteAddress, void *userData); #endif /* TZ_BLE_SERVER_H_ */ -- 2.7.4