#include "logger.h"
#include "oic_malloc.h"
+#include "oic_string.h"
#include "cathreadpool.h" /* for thread pool */
#include "camutex.h"
#include "uarraylist.h"
#include "org_iotivity_ca_CaLeClientInterface.h"
-#define TAG PCF("CA_LE_CLIENT")
+#define TAG PCF("OIC_CA_LE_CLIENT")
-static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
-static const char CLASSPATH_BT_ADAPTER[] = "android/bluetooth/BluetoothAdapter";
-static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
-static const char CLASSPATH_BT_GATT[] = "android/bluetooth/BluetoothGatt";
+#define MICROSECS_PER_SEC 1000000
+#define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
+
+static ca_thread_pool_t g_threadPoolHandle = NULL;
JavaVM *g_jvm;
static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
static CABLEErrorHandleCallback g_clientErrorCallback;
-static ca_thread_pool_t g_threadPoolHandle = NULL;
static jobject g_leScanCallback = NULL;
static jobject g_leGattCallback = NULL;
static jobject g_context = NULL;
static uint32_t g_targetCnt = 0;
static uint32_t g_currentSentCnt = 0;
static bool g_isFinishedSendData = false;
-static ca_mutex g_SendFinishMutex = false;
+static ca_mutex g_SendFinishMutex = NULL;
static ca_mutex g_threadMutex = NULL;
static ca_cond g_threadCond = NULL;
-
-static bool g_isRequestedSend = false;
-static bool g_isReceivedWriteCB = false;
-static ca_mutex g_writeCharacteristicCBMutex = false;
-static ca_mutex g_theSendRequestMutex = false;
-static ca_mutex g_threadSendCBMutex = NULL;
-static ca_cond g_threadSendCBCond = NULL;
+static ca_cond g_deviceDescCond = NULL;
static ca_mutex g_threadSendMutex = NULL;
-static ca_cond g_threadSendCond = NULL;
+static ca_mutex g_threadWriteCharacteristicMutex = NULL;
+static ca_cond g_threadWriteCharacteristicCond = NULL;
+static bool g_isSignalSetFlag = false;
static ca_mutex g_bleReqRespClientCbMutex = NULL;
static ca_mutex g_bleServerBDAddressMutex = NULL;
static ca_mutex g_gattObjectMutex = NULL;
static ca_mutex g_deviceStateListMutex = NULL;
-static CABLEClientDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
+static ca_mutex g_scanMutex = NULL;
+
+static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
+
+static jboolean g_autoConnectFlag = JNI_FALSE;
//getting jvm
void CALEClientJniInit()
return CA_STATUS_FAILED;
}
-CAResult_t CALEClientInitialize(ca_thread_pool_t handle)
+CAResult_t CALEClientInitialize()
{
OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
return ret;
}
- g_threadPoolHandle = handle;
-
ret = CALEClientInitGattMutexVaraibles();
if (CA_STATUS_OK != ret)
{
return ret;
}
+ g_deviceDescCond = ca_cond_new();
+
// init mutex for send logic
g_threadCond = ca_cond_new();
- g_threadSendCond = ca_cond_new();
- g_threadSendCBCond = ca_cond_new();
+ g_threadWriteCharacteristicCond = ca_cond_new();
CALEClientCreateDeviceList();
CALEClientJNISetContext();
}
g_isStartedLEClient = true;
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+
return CA_STATUS_OK;
}
}
g_isStartedMulticastServer = false;
- g_isStartedScan = false;
+ CALEClientSetScanFlag(false);
CALEClientSetSendFinishFlag(false);
- CALEClientSetTheSendRequestFlag(false);
- CALEClientSetWriteCharacteristicCBFlag(false);
CALEClientTerminateGattMutexVariables();
+ CALEClientDestroyJniInterface();
+ ca_cond_free(g_deviceDescCond);
ca_cond_free(g_threadCond);
- ca_cond_free(g_threadSendCond);
- ca_cond_free(g_threadSendCBCond);
+ ca_cond_free(g_threadWriteCharacteristicCond);
+
+ g_deviceDescCond = NULL;
+ g_threadCond = NULL;
+ g_threadWriteCharacteristicCond = NULL;
+ g_isSignalSetFlag = false;
+ CALEClientSetAutoConnectFlag(JNI_FALSE);
+
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+}
+
+CAResult_t CALEClientDestroyJniInterface()
+{
+ OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
+
+ if (!g_jvm)
+ {
+ OIC_LOG(ERROR, TAG, "g_jvm is null");
+ return CA_STATUS_FAILED;
+ }
+
+ bool isAttached = false;
+ JNIEnv* env;
+ jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+ if (JNI_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
+ res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+ if (JNI_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+ return CA_STATUS_FAILED;
+ }
+ isAttached = true;
+ }
+
+ jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
+ if (!jni_LeInterface)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
+ goto error_exit;
+ }
+
+ jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
+ "destroyLeInterface",
+ "()V");
+ if (!jni_InterfaceDestroyMethod)
+ {
+ OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
+ goto error_exit;
+ }
+
+ (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
+
+ if ((*env)->ExceptionCheck(env))
+ {
+ OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ goto error_exit;
+ }
+
+ OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
+
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+
+ return CA_STATUS_OK;
+
+error_exit:
if (isAttached)
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+
+ return CA_STATUS_FAILED;
}
void CALEClientSendFinish(JNIEnv *env, jobject gatt)
CALEClientUpdateSendCnt(env);
}
-CAResult_t CALEClientSendUnicastMessage(const char* address, const char* data,
+CAResult_t CALEClientSendUnicastMessage(const char* address,
+ const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %s)", address, data);
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
VERIFY_NON_NULL(address, TAG, "address is null");
VERIFY_NON_NULL(data, TAG, "data is null");
return CALEClientSendUnicastMessageImpl(address, data, dataLen);
}
-CAResult_t CALEClientSendMulticastMessage(const char* data, const uint32_t dataLen)
+CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
+ const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%s)", data);
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
VERIFY_NON_NULL(data, TAG, "data is null");
if (!g_jvm)
g_clientErrorCallback = callback;
}
-CAResult_t CALEClientGetInterfaceInfo(char **address)
+CAResult_t CALEClientIsThereScannedDevices()
{
- OIC_LOG(INFO, TAG, "CALEClientGetInterfaceInfo is not supported");
- return CA_NOT_SUPPORTED;
+ if (!g_deviceList)
+ {
+ return CA_STATUS_FAILED;
+ }
+
+ if (0 == u_arraylist_length(g_deviceList))
+ {
+ // Wait for LE peripherals to be discovered.
+
+ // Number of times to wait for discovery to complete.
+ static size_t const RETRIES = 5;
+
+ static uint64_t const TIMEOUT =
+ 2 * MICROSECS_PER_SEC; // Microseconds
+
+ bool devicesDiscovered = false;
+ for (size_t i = 0;
+ 0 == u_arraylist_length(g_deviceList) && i < RETRIES;
+ ++i)
+ {
+ if (ca_cond_wait_for(g_deviceDescCond,
+ g_threadSendMutex,
+ TIMEOUT) == CA_WAIT_SUCCESS)
+ {
+ devicesDiscovered = true;
+ break;
+ }
+ }
+
+ // time out for scanning devices
+ if (!devicesDiscovered)
+ {
+ return CA_STATUS_FAILED;
+ }
+ }
+
+ return CA_STATUS_OK;
}
-CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const char* data,
+CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %s", address,
+ OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
data);
VERIFY_NON_NULL(address, TAG, "address is null");
VERIFY_NON_NULL(data, TAG, "data is null");
ca_mutex_lock(g_threadSendMutex);
- CAResult_t ret = CA_STATUS_OK;
+ CALEClientSetSendFinishFlag(false);
+
+ CAResult_t ret = CALEClientIsThereScannedDevices();
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(INFO, TAG, "there is no scanned device");
+ goto error_exit;
+ }
+
if (g_context && g_deviceList)
{
uint32_t length = u_arraylist_length(g_deviceList);
if (g_sendBuffer)
{
(*env)->DeleteGlobalRef(env, g_sendBuffer);
+ g_sendBuffer = NULL;
}
jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
(*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+ // Target device to send message is just one.
+ g_targetCnt = 1;
+
ret = CALEClientSendData(env, jarrayObj);
if (CA_STATUS_OK != ret)
{
OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
goto error_exit;
}
- else
- {
- CALEClientSetTheSendRequestFlag(true);
- ca_cond_signal(g_threadSendCBCond);
-
- if (!g_isReceivedWriteCB)
- {
- OIC_LOG(INFO, TAG, "wait..(unicast)");
- ca_cond_wait(g_threadSendCond, g_threadSendMutex);
- }
- else
- {
- CALEClientSetWriteCharacteristicCBFlag(false);
- }
- }
OIC_LOG(INFO, TAG, "wake up");
break;
}
}
- if (isAttached)
+ OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
+
+ // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
+ // if there is no connection state.
+ ca_mutex_lock(g_threadMutex);
+ if (!g_isFinishedSendData)
{
- (*g_jvm)->DetachCurrentThread(g_jvm);
+ OIC_LOG(DEBUG, TAG, "waiting send finish signal");
+ ca_cond_wait(g_threadCond, g_threadMutex);
+ OIC_LOG(DEBUG, TAG, "the data was sent");
}
+ ca_mutex_unlock(g_threadMutex);
- ret = CALECheckSendState(address);
- if(CA_STATUS_OK != ret)
+ if (isAttached)
{
- OIC_LOG(ERROR, TAG, "send has failed");
- goto error_exit;
+ (*g_jvm)->DetachCurrentThread(g_jvm);
}
// start LE Scan again
}
ca_mutex_unlock(g_threadSendMutex);
- OIC_LOG(INFO, TAG, "unicast - send success");
- return CA_STATUS_OK;
+ OIC_LOG(INFO, TAG, "unicast - send logic has finished");
+ return CALECheckSendState(address);
// error label.
error_exit:
{
OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
ca_mutex_unlock(g_threadSendMutex);
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
return res;
}
{
(*g_jvm)->DetachCurrentThread(g_jvm);
}
+
+ if (g_clientErrorCallback)
+ {
+ g_clientErrorCallback(address, data, dataLen, CA_SEND_FAILED);
+ }
ca_mutex_unlock(g_threadSendMutex);
return CA_SEND_FAILED;
}
-CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const char* data,
+CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
const uint32_t dataLen)
{
- OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
+ OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
VERIFY_NON_NULL(data, TAG, "data is null");
VERIFY_NON_NULL(env, TAG, "env is null");
if (g_sendBuffer)
{
(*env)->DeleteGlobalRef(env, g_sendBuffer);
+ g_sendBuffer = NULL;
+ }
+
+ CAResult_t res = CALEClientIsThereScannedDevices();
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "there is no scanned device");
+ goto error_exit;
}
- jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
- (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
- g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
// connect to gatt server
- CAResult_t res = CALEClientStopScan();
+ res = CALEClientStopScan();
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
ca_mutex_unlock(g_threadSendMutex);
return res;
}
-
uint32_t length = u_arraylist_length(g_deviceList);
g_targetCnt = length;
- if (0 == length)
- {
- goto error_exit;
- }
+
+ jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+ (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+ g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
for (uint32_t index = 0; index < length; index++)
{
res = CALEClientSendData(env, jarrayObj);
if (res != CA_STATUS_OK)
{
- OIC_LOG(ERROR, TAG, "BT device[%d] - send has failed");
- }
- else
- {
- CALEClientSetTheSendRequestFlag(true);
- ca_cond_signal(g_threadSendCBCond);
-
- if (!g_isReceivedWriteCB)
- {
- OIC_LOG(INFO, TAG, "wait..(multicast)");
- ca_cond_wait(g_threadSendCond, g_threadSendMutex);
- }
- else
- {
- CALEClientSetWriteCharacteristicCBFlag(false);
- }
+ OIC_LOG(ERROR, TAG, "BT device - send has failed");
}
jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
continue;
}
- res = CALECheckSendState(address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG_V(INFO, TAG, "multicast : send has failed for this device[%s]", address);
- g_clientErrorCallback(address, data, dataLen, res);
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- continue;
- }
-
(*env)->ReleaseStringUTFChars(env, jni_address, address);
}
- OIC_LOG(DEBUG, TAG, "connection routine is finished");
+ OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
// wait for finish to send data through "CALeGattServicesDiscoveredCallback"
+ ca_mutex_lock(g_threadMutex);
if (!g_isFinishedSendData)
{
- ca_mutex_lock(g_threadMutex);
+ OIC_LOG(DEBUG, TAG, "waiting send finish signal");
ca_cond_wait(g_threadCond, g_threadMutex);
- OIC_LOG(DEBUG, TAG, "the data was sent for All devices");
- ca_mutex_unlock(g_threadMutex);
+ OIC_LOG(DEBUG, TAG, "the data was sent");
}
+ ca_mutex_unlock(g_threadMutex);
// start LE Scan again
res = CALEClientStartScan();
ca_mutex_unlock(g_deviceStateListMutex);
return CA_SEND_FAILED;
}
+
+ OIC_LOG(INFO, TAG, "sendstate is STATE_SEND_SUCCESS");
ca_mutex_unlock(g_deviceStateListMutex);
return CA_STATUS_OK;
}
VERIFY_NON_NULL(device, TAG, "device is null");
VERIFY_NON_NULL(env, TAG, "env is null");
- jstring jni_address = CALEGetAddressFromBTDevice(env, device);
- if (!jni_address)
- {
- OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
- return CA_STATUS_FAILED;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
+ // get BLE address from bluetooth device object.
+ char* address = NULL;
+ CALEState_t* state = NULL;
+ jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
+ if (jni_address)
{
- OIC_LOG(ERROR, TAG, "address is not available");
- return CA_STATUS_FAILED;
+ OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
+ address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is not available");
+ return CA_STATUS_FAILED;
+ }
+ ca_mutex_lock(g_deviceStateListMutex);
+ state = CALEClientGetStateInfo(address);
+ ca_mutex_unlock(g_deviceStateListMutex);
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
}
- ca_mutex_lock(g_deviceStateListMutex);
- CALEState_t* state = CALEClientGetStateInfo(address);
- ca_mutex_unlock(g_deviceStateListMutex);
if (!state)
{
OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
- CAResult_t ret = CALEClientConnect(env, device, JNI_FALSE, g_leGattCallback);
- if (CA_STATUS_OK != ret)
+
+ // cancel previous connection request before connection
+ // if there is gatt object in g_gattObjectList.
+ if (jni_address)
{
- OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
+ address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is not available");
+ return CA_STATUS_FAILED;
+ }
+
+ jobject gatt = CALEClientGetGattObjInList(env, address);
+ if (gatt)
+ {
+ CAResult_t res = CALEClientDisconnect(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "there is no gatt object");
+ }
+ }
(*env)->ReleaseStringUTFChars(env, jni_address, address);
- return ret;
+ }
+
+ // connection request
+ jobject newGatt = CALEClientConnect(env, device, CALEClientGetAutoConnectFlag());
+ if (NULL == newGatt)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
+ return CA_STATUS_FAILED;
}
}
else
if (STATE_CONNECTED == state->connectedState)
{
OIC_LOG(INFO, TAG, "GATT has already connected");
+ if (!jni_address)
+ {
+ OIC_LOG(ERROR, TAG, "jni_address is not available");
+ return CA_STATUS_FAILED;
+ }
+
+ address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is not available");
+ return CA_STATUS_FAILED;
+ }
+
jobject gatt = CALEClientGetGattObjInList(env, address);
if (!gatt)
{
return CA_STATUS_FAILED;
}
- CAResult_t ret = CALEClientWriteCharacteristic(env, gatt);
+ CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
if (CA_STATUS_OK != ret)
{
- OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+ OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
(*env)->ReleaseStringUTFChars(env, jni_address, address);
return ret;
}
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
}
else
{
+ OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
+
+ // cancel previous connection request before connection
+ // if there is gatt object in g_gattObjectList.
+ if (jni_address)
+ {
+ address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is not available");
+ return CA_STATUS_FAILED;
+ }
+
+ jobject gatt = CALEClientGetGattObjInList(env, address);
+ if (gatt)
+ {
+ CAResult_t res = CALEClientDisconnect(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "there is no gatt object");
+ }
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ }
+
OIC_LOG(DEBUG, TAG, "start to connect LE");
- CAResult_t ret = CALEClientConnect(env, device, JNI_FALSE, g_leGattCallback);
- if (CA_STATUS_OK != ret)
+ jobject gatt = CALEClientConnect(env, device, JNI_TRUE);
+ if (NULL == gatt)
{
OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- return ret;
+ return CA_STATUS_FAILED;
}
}
}
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
return CA_STATUS_OK;
}
{
#ifdef UUID_SCAN
ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
- if(CA_STATUS_OK != ret)
- {
- OIC_LOG(ERROR, TAG, "CALEClientStartScanWithUUIDImpl has failed");
- }
#else
ret = CALEClientStartScanImpl(env, g_leScanCallback);
+#endif
if (CA_STATUS_OK != ret)
{
- OIC_LOG(ERROR, TAG, "CALEClientStartScanImpl has failed");
+ if (CA_ADAPTER_NOT_ENABLED == ret)
+ {
+ OIC_LOG(DEBUG, TAG, "Adapter is disabled");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "start scan has failed");
+ }
}
-#endif
}
if (isAttached)
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
else
{
OIC_LOG(DEBUG, TAG, "startLeScan is started");
- g_isStartedScan = true;
+ CALEClientSetScanFlag(true);
}
return CA_STATUS_OK;
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
else
{
OIC_LOG(DEBUG, TAG, "startLeScan With UUID is started");
- g_isStartedScan = true;
+ CALEClientSetScanFlag(true);
}
return CA_STATUS_OK;
CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
if (CA_STATUS_OK != ret)
{
- OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
+ if (CA_ADAPTER_NOT_ENABLED == ret)
+ {
+ OIC_LOG(DEBUG, TAG, "Adapter is disabled");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
+ }
}
else
{
- g_isStartedScan = false;
+ CALEClientSetScanFlag(false);
}
if (isAttached)
return ret;
}
+void CALEClientSetScanFlag(bool flag)
+{
+ ca_mutex_lock(g_scanMutex);
+ g_isStartedScan = flag;
+ ca_mutex_unlock(g_scanMutex);
+}
+
CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
{
OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
return CA_STATUS_OK;
}
-CAResult_t CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect,
- jobject callback)
+void CALEClientSetAutoConnectFlag(jboolean flag)
{
- OIC_LOG(DEBUG, TAG, "GATT CONNECT");
- VERIFY_NON_NULL(env, TAG, "env is null");
- VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
- VERIFY_NON_NULL(callback, TAG, "callback is null");
+ OIC_LOG_V(INFO, TAG, "auto connect flag is set %d", flag);
+ g_autoConnectFlag = flag;
+}
- if (!CALEIsEnableBTAdapter(env))
- {
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
- return CA_ADAPTER_NOT_ENABLED;
- }
+jboolean CALEClientGetAutoConnectFlag()
+{
+ OIC_LOG_V(INFO, TAG, "auto connect flag is %d", g_autoConnectFlag);
+ return g_autoConnectFlag;
+}
+
+jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
+{
+ OIC_LOG(DEBUG, TAG, "CALEClientConnect");
+ VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+ VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
+
+ // get gatt object from Bluetooth Device object for closeProfileProxy(..)
+ jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
+ if (jni_address)
+ {
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is not available");
+ return NULL;
+ }
+
+ // close the gatt service
+ jobject gatt = CALEClientGetGattObjInList(env, address);
+ if (gatt)
+ {
+ CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ return NULL;
+ }
+
+ // clean previous gatt object after close profile service
+ res = CALEClientRemoveGattObjForAddr(env, jni_address);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ return NULL;
+ }
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ }
+
+ jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
+ if (!newGatt)
+ {
+ OIC_LOG(DEBUG, TAG, "re-connection will be started");
+ return NULL;
+ }
+
+ // add new gatt object into g_gattObjectList
+ CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
+ return NULL;
+ }
+
+ return newGatt;
+}
+
+jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
+{
+ OIC_LOG(DEBUG, TAG, "GATT CONNECT");
+ VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
+ VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
+
+ if (!CALEIsEnableBTAdapter(env))
+ {
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+ return NULL;
+ }
jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
if (!jni_address)
{
OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
- return CA_STATUS_FAILED;
+ return NULL;
}
// get BluetoothDevice class
if (!jni_cid_BluetoothDevice)
{
OIC_LOG(ERROR, TAG, "bleConnect: jni_cid_BluetoothDevice is null");
- return CA_STATUS_FAILED;
+ return NULL;
}
// get connectGatt method
if (!jni_mid_connectGatt)
{
OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
- return CA_STATUS_FAILED;
+ return NULL;
}
- OIC_LOG(DEBUG, TAG, "Call object method - connectGatt");
+ OIC_LOG(INFO, TAG, "CALL API - connectGatt");
jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
jni_mid_connectGatt,
NULL,
- autoconnect, callback);
+ autoconnect, g_leGattCallback);
if (!jni_obj_connectGatt)
{
- OIC_LOG(ERROR, TAG, "CALL API - connectGatt was failed..it will be removed");
+ OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
CALEClientUpdateSendCnt(env);
- return CA_STATUS_FAILED;
+ return NULL;
}
else
{
OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
}
+ return jni_obj_connectGatt;
+}
+
+CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
+{
+ OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
+
+ VERIFY_NON_NULL(env, TAG, "env is null");
+ VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+
+ jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
+ if (!jni_cid_BTAdapter)
+ {
+ OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
+ return CA_STATUS_FAILED;
+ }
+
+ // get remote bt adapter method
+ jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
+ "getDefaultAdapter",
+ METHODID_OBJECTNONPARAM);
+ if (!jni_mid_getDefaultAdapter)
+ {
+ OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
+ return CA_STATUS_FAILED;
+ }
+
+ // gat bt adapter object
+ jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
+ jni_mid_getDefaultAdapter);
+ if (!jni_obj_BTAdapter)
+ {
+ OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
+ return CA_STATUS_FAILED;
+ }
+
+ // get closeProfileProxy method
+ jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
+ "closeProfileProxy",
+ "(ILandroid/bluetooth/"
+ "BluetoothProfile;)V");
+ if (!jni_mid_closeProfileProxy)
+ {
+ OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
+ return CA_STATUS_FAILED;
+ }
+
+ jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
+ if (!jni_cid_BTProfile)
+ {
+ OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
+ return CA_STATUS_FAILED;
+ }
+
+ // GATT - Constant value : 7 (0x00000007)
+ jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
+ "GATT", "I");
+ if (!id_gatt)
+ {
+ OIC_LOG(ERROR, TAG, "id_gatt is null");
+ return CA_STATUS_FAILED;
+ }
+
+ jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
+
+ OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
+ (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
+ if ((*env)->ExceptionCheck(env))
+ {
+ OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
+ (*env)->ExceptionDescribe(env);
+ (*env)->ExceptionClear(env);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
return CA_STATUS_OK;
}
+
CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
{
OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
VERIFY_NON_NULL(env, TAG, "env is null");
VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
- if (!CALEIsEnableBTAdapter(env))
- {
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
- return CA_ADAPTER_NOT_ENABLED;
- }
-
// get BluetoothGatt class
jclass jni_cid_BluetoothGatt = (*env)->FindClass(env, CLASSPATH_BT_GATT);
if (!jni_cid_BluetoothGatt)
}
// call disconnect gatt method
+ OIC_LOG(DEBUG, TAG, "CALL API - request disconnect gatt");
(*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
if ((*env)->ExceptionCheck(env))
{
if (!g_gattObjectList)
{
- OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
- return CA_STATUS_FAILED;
+ OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+ return CA_STATUS_OK;
}
uint32_t length = u_arraylist_length(g_gattObjectList);
+ OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
for (uint32_t index = 0; index < length; index++)
{
+ OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
if (!jarrayObj)
{
}
}
- OICFree(g_gattObjectList);
- g_gattObjectList = NULL;
+ return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
+{
+ OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
+ VERIFY_NON_NULL(env, TAG, "env is null");
+ if (!g_gattObjectList)
+ {
+ OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
+ return CA_STATUS_OK;
+ }
+
+ char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is null");
+ return CA_STATUS_FAILED;
+ }
+
+ uint32_t length = u_arraylist_length(g_gattObjectList);
+ for (uint32_t index = 0; index < length; index++)
+ {
+ jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+ if (!jarrayObj)
+ {
+ OIC_LOG(ERROR, TAG, "jarrayObj is null");
+ continue;
+ }
+
+ jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+ if (!jni_setAddress)
+ {
+ OIC_LOG(ERROR, TAG, "jni_setAddress is null");
+ (*env)->ReleaseStringUTFChars(env, remote_address, address);
+ return CA_STATUS_FAILED;
+ }
+
+ const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
+ if (!setAddress)
+ {
+ OIC_LOG(ERROR, TAG, "setAddress is null");
+ (*env)->ReleaseStringUTFChars(env, remote_address, address);
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
+ if (!strcmp(address, setAddress))
+ {
+ CAResult_t res = CALEClientDisconnect(env, jarrayObj);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
+ (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+ (*env)->ReleaseStringUTFChars(env, remote_address, address);
+ return CA_STATUS_FAILED;
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+ (*env)->ReleaseStringUTFChars(env, remote_address, address);
+ return CA_STATUS_OK;
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
+ }
+ (*env)->ReleaseStringUTFChars(env, remote_address, address);
+
+ OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
return CA_STATUS_OK;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
return CA_STATUS_OK;
}
-CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
+static void CALEWriteCharacteristicThread(void* object)
+{
+ VERIFY_NON_NULL_VOID(object, TAG, "object is null");
+
+ bool isAttached = false;
+ JNIEnv* env;
+ jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
+ if (JNI_OK != res)
+ {
+ OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
+ res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
+
+ if (JNI_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
+ return;
+ }
+ isAttached = true;
+ }
+
+ jobject gatt = (jobject)object;
+ CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
+ if (CA_STATUS_OK != ret)
+ {
+ OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
+ }
+
+ if (isAttached)
+ {
+ (*g_jvm)->DetachCurrentThread(g_jvm);
+ }
+}
+
+CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
{
- VERIFY_NON_NULL(env, TAG, "env is null");
VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+ VERIFY_NON_NULL(env, TAG, "env is null");
// send data
jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
if (!jni_obj_character)
{
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return CA_STATUS_FAILED;
}
if (CA_STATUS_OK != ret)
{
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
- return ret;
+ return CA_STATUS_FAILED;
}
+ // wait for callback for write Characteristic with success to sent data
+ OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
+ 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))
+ {
+ OIC_LOG(ERROR, TAG, "there is no response. write has failed");
+ g_isSignalSetFlag = false;
+ ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+ return CA_STATUS_FAILED;
+ }
+ }
+ // reset flag set by writeCharacteristic Callback
+ g_isSignalSetFlag = false;
+ ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+ OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
+ return CA_STATUS_OK;
+}
+
+CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
+{
+ OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
+ VERIFY_NON_NULL(env, TAG, "env is null");
+ VERIFY_NON_NULL(gatt, TAG, "gatt is null");
+
+ jobject gattParam = (*env)->NewGlobalRef(env, gatt);
+ if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
+ CALEWriteCharacteristicThread, (void*)gattParam))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to create read thread!");
+ return CA_STATUS_FAILED;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
return CA_STATUS_OK;
}
CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
- jobject gattCharacteristic)
+ jobject gattCharacteristic)
{
OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
VERIFY_NON_NULL(env, TAG, "env is null");
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_STATUS_FAILED;
}
gattCharacteristic);
if (ret)
{
- OIC_LOG(DEBUG, TAG, "writeCharacteristic success");
+ OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
}
else
{
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_STATUS_FAILED;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return NULL;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return NULL;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return NULL;
}
if (!CALEIsEnableBTAdapter(env))
{
- OIC_LOG(ERROR, TAG, "BT adapter is not enabled");
+ OIC_LOG(INFO, TAG, "BT adapter is not enabled");
return CA_ADAPTER_NOT_ENABLED;
}
jni_mid_getDescriptor, jni_obj_cc_uuid);
if (!jni_obj_descriptor)
{
- OIC_LOG(ERROR, TAG, "jni_obj_descriptor is null");
- return CA_STATUS_FAILED;
+ OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
+ return CA_NOT_SUPPORTED;
}
OIC_LOG(DEBUG, TAG, "set value in descriptor");
CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
{
- OIC_LOG(DEBUG, TAG, "IN - CALEClientAddScanDeviceToList");
VERIFY_NON_NULL(device, TAG, "device is null");
VERIFY_NON_NULL(env, TAG, "env is null");
{
jobject gdevice = (*env)->NewGlobalRef(env, device);
u_arraylist_add(g_deviceList, gdevice);
- OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
+ ca_cond_signal(g_deviceDescCond);
+ OIC_LOG_V(DEBUG, TAG, "Added this BT Device[%s] in the List", remoteAddress);
}
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
ca_mutex_unlock(g_deviceListMutex);
- OIC_LOG(DEBUG, TAG, "OUT - CALEClientAddScanDeviceToList");
return CA_STATUS_OK;
}
bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
{
- OIC_LOG(DEBUG, TAG, "IN - CALEClientIsDeviceInScanDeviceList");
VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
if (!strcmp(remoteAddress, setAddress))
{
- OIC_LOG(DEBUG, TAG, "the device is already set");
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
return true;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
}
- OIC_LOG(DEBUG, TAG, "OUT - CALEClientIsDeviceInScanDeviceList");
OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
return false;
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, address, remoteAddress);
- CALEClientReorderingList(index, g_deviceList);
+ if (NULL == u_arraylist_remove(g_deviceList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_deviceListMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_deviceListMutex);
return CA_STATUS_OK;
}
CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
{
- OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
+ OIC_LOG(INFO, TAG, "CALEClientAddGattobjToList");
VERIFY_NON_NULL(env, TAG, "env is null");
VERIFY_NON_NULL(gatt, TAG, "gatt is null");
ca_mutex_lock(g_gattObjectMutex);
+ if (!g_gattObjectList)
+ {
+ OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
+ ca_mutex_unlock(g_gattObjectMutex);
+ return CA_STATUS_FAILED;
+ }
+
jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
if (!jni_remoteAddress)
{
return CA_STATUS_FAILED;
}
+ OIC_LOG_V(INFO, TAG, "remote address : %s", remoteAddress);
if (!CALEClientIsGattObjInList(env, remoteAddress))
{
jobject newGatt = (*env)->NewGlobalRef(env, gatt);
u_arraylist_add(g_gattObjectList, newGatt);
- OIC_LOG(DEBUG, TAG, "Set GATT Object to Array as Element");
+ OIC_LOG(INFO, TAG, "Set GATT Object to Array as Element");
}
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
ca_mutex_lock(g_gattObjectMutex);
if (!g_gattObjectList)
{
- OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
+ OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
ca_mutex_unlock(g_gattObjectMutex);
- return CA_STATUS_FAILED;
+ return CA_STATUS_OK;
}
uint32_t length = u_arraylist_length(g_gattObjectList);
OICFree(g_gattObjectList);
g_gattObjectList = NULL;
+ OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
ca_mutex_unlock(g_gattObjectMutex);
return CA_STATUS_OK;
}
ca_mutex_lock(g_gattObjectMutex);
if (!g_gattObjectList)
{
- OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
+ OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
ca_mutex_unlock(g_gattObjectMutex);
- return CA_STATUS_FAILED;
+ return CA_STATUS_OK;
}
uint32_t length = u_arraylist_length(g_gattObjectList);
(*env)->DeleteGlobalRef(env, jarrayObj);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
+
+ if (NULL == u_arraylist_remove(g_gattObjectList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_gattObjectMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_gattObjectMutex);
- return CALEClientReorderingList(index, g_gattObjectList);
+ return CA_STATUS_OK;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
ca_mutex_lock(g_gattObjectMutex);
if (!g_gattObjectList)
{
- OIC_LOG(ERROR, TAG, "g_gattObjectList is null");
+ OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
ca_mutex_unlock(g_gattObjectMutex);
- return CA_STATUS_FAILED;
+ return CA_STATUS_OK;
}
uint32_t length = u_arraylist_length(g_gattObjectList);
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
+ if (NULL == u_arraylist_remove(g_gattObjectList, index))
+ {
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ ca_mutex_unlock(g_gattObjectMutex);
+ return CA_STATUS_FAILED;
+ }
ca_mutex_unlock(g_gattObjectMutex);
- return CALEClientReorderingList(index, g_gattObjectList);
+ return CA_STATUS_OK;
}
(*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
(*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
return CA_STATUS_FAILED;
}
+jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
+{
+ OIC_LOG(DEBUG, TAG, "IN - CALEClientGetLEAddressFromBTDevice");
+
+ VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
+ VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
+
+ // get Bluetooth Address
+ jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
+ if (!jni_btTargetAddress)
+ {
+ OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
+ return NULL;
+ }
+
+ const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
+ if (!targetAddress)
+ {
+ OIC_LOG(ERROR, TAG, "targetAddress is not available");
+ return NULL;
+ }
+
+ // get method ID of getDevice()
+ jclass jni_cid_gattdevice_list = (*env)->FindClass(env, CLASSPATH_BT_GATT);
+ if (!jni_cid_gattdevice_list)
+ {
+ OIC_LOG(ERROR, TAG, "jni_cid_gattdevice_list is null");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ jmethodID jni_mid_getDevice = (*env)->GetMethodID(env, jni_cid_gattdevice_list, "getDevice",
+ METHODID_BT_DEVICE);
+ if (!jni_mid_getDevice)
+ {
+ OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ size_t length = u_arraylist_length(g_gattObjectList);
+ for (size_t index = 0; index < length; index++)
+ {
+ jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
+ if (!jarrayObj)
+ {
+ OIC_LOG(ERROR, TAG, "jarrayObj is null");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TAG, "CALL API - bluetoothGatt.getDevice()");
+ jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
+ if (!jni_obj_device)
+ {
+ OIC_LOG(ERROR, TAG, "jni_obj_device is null");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
+ if (!jni_btAddress)
+ {
+ OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
+ if (!btAddress)
+ {
+ OIC_LOG(ERROR, TAG, "btAddress is not available");
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ return NULL;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
+ OIC_LOG_V(DEBUG, TAG, "btAddress : %s", btAddress);
+ if (!strcmp(targetAddress, btAddress))
+ {
+ OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
+
+ // get LE address
+ jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
+ if (!jni_LEAddress)
+ {
+ OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
+ (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
+ (*env)->DeleteLocalRef(env, jni_btAddress);
+ (*env)->DeleteLocalRef(env, jni_obj_device);
+ return jni_LEAddress;
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
+ (*env)->DeleteLocalRef(env, jni_btAddress);
+ (*env)->DeleteLocalRef(env, jni_obj_device);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetLEAddressFromBTDevice");
+ return NULL;
+}
+
/**
* BT State List
*/
}
}
u_arraylist_add(g_deviceStateList, state); // update new state
- OIC_LOG_V(DEBUG, TAG, "Set State Info to List : %d, %d",
- state->connectedState, state->notificationState);
+ OIC_LOG_V(INFO, TAG, "Set State Info to List : %d, %d, %s",
+ state->connectedState, state->notificationState, state->address);
ca_mutex_unlock(g_deviceStateListMutex);
return CA_STATUS_OK;
CAResult_t CALEClientRemoveAllDeviceState()
{
- OIC_LOG(DEBUG, TAG, "CALENativeRemoveAllDevices");
+ OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
ca_mutex_lock(g_deviceStateListMutex);
if (!g_deviceStateList)
if (!strcmp(state->address, remoteAddress))
{
- OIC_LOG_V(DEBUG, TAG, "remove state : %s", remoteAddress);
- OICFree(state);
+ OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
- CAResult_t res = CALEClientReorderingList(index, g_deviceStateList);
- if(CA_STATUS_OK != res)
+ CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
+ index);
+ if (NULL == targetState)
{
- OIC_LOG(ERROR, TAG, "CALEClientReorderingList has failed");
- return res;
+ OIC_LOG(ERROR, TAG, "List removal failed.");
+ return CA_STATUS_FAILED;
}
+
+ OICFree(targetState);
return CA_STATUS_OK;
}
}
- return CA_STATUS_FAILED;
+ return CA_STATUS_OK;
}
CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
}
uint32_t length = u_arraylist_length(g_deviceStateList);
+ OIC_LOG_V(DEBUG, TAG, "CALEClientGetStateInfo : %d", length);
+
for (uint32_t index = 0; index < length; index++)
{
CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
continue;
}
+ OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
+ OIC_LOG_V(DEBUG, TAG, "state address : %s", state->address);
+
if (!strcmp(state->address, remoteAddress))
{
OIC_LOG_V(DEBUG, TAG, "get state : %s", remoteAddress);
}
}
-CAResult_t CALEClientReorderingList(uint32_t index, u_arraylist_t *list)
-{
- if (!list)
- {
- OIC_LOG(ERROR, TAG, "list is null");
- return CA_STATUS_FAILED;
- }
-
- if (index >= list->length)
- {
- OIC_LOG(ERROR, TAG, "index is not available");
- return CA_STATUS_FAILED;
- }
-
- if (index < list->length - 1)
- {
- memmove(&list->data[index], &list->data[index + 1],
- (list->length - index - 1) * sizeof(void *));
- }
-
- list->size--;
- list->length--;
-
- return CA_STATUS_OK;
-}
-
/**
* Check Sent Count for remove g_sendBuffer
*/
void CALEClientUpdateSendCnt(JNIEnv *env)
{
+ OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
+
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
// mutex lock
ca_mutex_lock(g_threadMutex);
}
// notity the thread
ca_cond_signal(g_threadCond);
+
CALEClientSetSendFinishFlag(true);
OIC_LOG(DEBUG, TAG, "set signal for send data");
}
CAResult_t CALEClientInitGattMutexVaraibles()
{
- OIC_LOG(DEBUG, TAG, "IN");
-
if (NULL == g_bleReqRespClientCbMutex)
{
g_bleReqRespClientCbMutex = ca_mutex_new();
}
}
- if (NULL == g_threadSendCBMutex)
- {
- g_threadSendCBMutex = ca_mutex_new();
- if (NULL == g_threadSendCBMutex)
- {
- OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
- return CA_STATUS_FAILED;
- }
- }
-
if (NULL == g_deviceListMutex)
{
g_deviceListMutex = ca_mutex_new();
}
}
- if (NULL == g_writeCharacteristicCBMutex)
+ if (NULL == g_scanMutex)
{
- g_writeCharacteristicCBMutex = ca_mutex_new();
- if (NULL == g_writeCharacteristicCBMutex)
+ g_scanMutex = ca_mutex_new();
+ if (NULL == g_scanMutex)
{
OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
return CA_STATUS_FAILED;
}
}
- if (NULL == g_theSendRequestMutex)
+ if (NULL == g_threadWriteCharacteristicMutex)
{
- g_theSendRequestMutex = ca_mutex_new();
- if (NULL == g_theSendRequestMutex)
+ g_threadWriteCharacteristicMutex = ca_mutex_new();
+ if (NULL == g_threadWriteCharacteristicMutex)
{
OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
return CA_STATUS_FAILED;
}
}
- OIC_LOG(DEBUG, TAG, "OUT");
return CA_STATUS_OK;
}
void CALEClientTerminateGattMutexVariables()
{
- OIC_LOG(DEBUG, TAG, "IN");
-
ca_mutex_free(g_bleReqRespClientCbMutex);
g_bleReqRespClientCbMutex = NULL;
ca_mutex_free(g_threadSendMutex);
g_threadSendMutex = NULL;
- ca_mutex_free(g_threadSendCBMutex);
- g_threadSendCBMutex = NULL;
-
ca_mutex_free(g_deviceListMutex);
g_deviceListMutex = NULL;
ca_mutex_free(g_SendFinishMutex);
g_SendFinishMutex = NULL;
- ca_mutex_free(g_writeCharacteristicCBMutex);
- g_writeCharacteristicCBMutex = NULL;
+ ca_mutex_free(g_scanMutex);
+ g_scanMutex = NULL;
- ca_mutex_free(g_theSendRequestMutex);
- g_theSendRequestMutex = NULL;
-
- OIC_LOG(DEBUG, TAG, "OUT");
+ ca_mutex_free(g_threadWriteCharacteristicMutex);
+ g_threadWriteCharacteristicMutex = NULL;
}
void CALEClientSetSendFinishFlag(bool flag)
ca_mutex_unlock(g_SendFinishMutex);
}
-void CALEClientSetWriteCharacteristicCBFlag(bool flag)
-{
- OIC_LOG_V(DEBUG, TAG, "g_isReceivedWriteCB is %d", flag);
-
- ca_mutex_lock(g_writeCharacteristicCBMutex);
- g_isReceivedWriteCB = flag;
- ca_mutex_unlock(g_writeCharacteristicCBMutex);
-}
-
-void CALEClientSetTheSendRequestFlag(bool flag)
-{
- OIC_LOG_V(DEBUG, TAG, "g_isRequestedSend is %d", flag);
-
- ca_mutex_lock(g_theSendRequestMutex);
- g_isRequestedSend = flag;
- ca_mutex_unlock(g_theSendRequestMutex);
-}
-
/**
* adapter common
*/
OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
}
+ ca_mutex_lock(g_threadMutex);
ca_cond_signal(g_threadCond);
- ca_cond_signal(g_threadSendCond);
- g_isStartedLEClient = false;
+ ca_mutex_unlock(g_threadMutex);
+
+ ca_mutex_lock(g_threadWriteCharacteristicMutex);
+ ca_cond_signal(g_threadWriteCharacteristicCond);
+ ca_mutex_unlock(g_threadWriteCharacteristicMutex);
if (isAttached)
{
}
+CAResult_t CAInitializeLEGattClient()
+{
+ OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
+ CALEClientInitialize();
+ return CA_STATUS_OK;
+}
+
void CATerminateLEGattClient()
{
OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
+ CAStopLEGattClient();
CALEClientTerminate();
}
-CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const char *data,
- const uint32_t dataLen, CALETransferType_t type,
- const int32_t position)
+CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
+ uint32_t dataLen, CALETransferType_t type,
+ int32_t position)
{
OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
VERIFY_NON_NULL(data, TAG, "data is null");
VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
+ if (LE_UNICAST != type || position < 0)
+ {
+ OIC_LOG(ERROR, TAG, "this request is not unicast");
+ return CA_STATUS_INVALID_PARAM;
+ }
+
return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
}
-CAResult_t CAUpdateCharacteristicsToAllGattServers(const char *data, uint32_t dataLen)
+CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
{
OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
VERIFY_NON_NULL(data, TAG, "data is null");
return CALEClientSendMulticastMessage(data, dataLen);
}
-void CASetLEReqRespClientCallback(CABLEClientDataReceivedCallback callback)
+void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
{
- OIC_LOG(DEBUG, TAG, "IN");
-
ca_mutex_lock(g_bleReqRespClientCbMutex);
g_CABLEClientDataReceivedCallback = callback;
ca_mutex_unlock(g_bleReqRespClientCbMutex);
-
- OIC_LOG(DEBUG, TAG, "OUT");
}
void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
{
- OIC_LOG(DEBUG, TAG, "IN");
-
- CALEClientInitialize(handle);
-
- OIC_LOG(DEBUG, TAG, "OUT");
+ g_threadPoolHandle = handle;
}
CAResult_t CAGetLEAddress(char **local_address)
{
- OIC_LOG(DEBUG, TAG, "IN");
-
- VERIFY_NON_NULL(local_address, TAG, "local_address is null");
- CAResult_t res = CALEClientGetInterfaceInfo(local_address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(INFO, TAG, "it didn't get local address");
- }
-
- OIC_LOG(DEBUG, TAG, "OUT");
- return CA_STATUS_OK;
+ VERIFY_NON_NULL(local_address, TAG, "local_address");
+ OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
+ return CA_NOT_SUPPORTED;
}
JNIEXPORT void JNICALL
{
OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
g_leScanCallback = (*env)->NewGlobalRef(env, callback);
{
OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
g_leGattCallback = (*env)->NewGlobalRef(env, callback);
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
- jobject device, jint rssi,
- jbyteArray scanRecord)
+ jobject device)
{
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(device, TAG, "device is null");
CAResult_t res = CALEClientAddScanDeviceToList(env, device);
OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
newstate);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
- if (GATT_SUCCESS == status && STATE_CONNECTED == newstate) // le connected
+ jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
+ jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
+ jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+
+ if (gatt_success == status && state_connected == newstate) // le connected
{
jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
if (!jni_address)
(*env)->ReleaseStringUTFChars(env, jni_address, address);
goto error_exit;
}
+ OIC_LOG_V(INFO, TAG, "ConnectionStateCB - remote address : %s", address);
+
(*env)->ReleaseStringUTFChars(env, jni_address, address);
}
goto error_exit;
}
}
- else if (GATT_SUCCESS == status && STATE_DISCONNECTED == newstate) // le disconnected
+ else if (GATT_ERROR == status && state_disconnected == newstate)
+ {
+ OIC_LOG(INFO, TAG, "Background connection running.. please wait");
+ }
+ else // le disconnected
{
CAResult_t res = CALEClientStartScan();
if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+ if (CA_ADAPTER_NOT_ENABLED == res)
+ {
+ // scan will be started with start server when adapter is enabled
+ OIC_LOG(INFO, TAG, "Adapter was disabled");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
+ goto error_exit;
+ }
}
jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
if (!jni_address)
{
OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
+ goto error_exit;
}
const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
if (address)
{
- res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
- STATE_CHARACTER_NO_CHANGE,
- STATE_SEND_NONE);
+ CAResult_t res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
+ STATE_CHARACTER_UNSET,
+ STATE_SEND_NONE);
if (CA_STATUS_OK != res)
{
OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ goto error_exit;
}
+ OIC_LOG_V(INFO, TAG, "ConnectionStateCB - remote address : %s", address);
+
(*env)->ReleaseStringUTFChars(env, jni_address, address);
}
OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
}
- ca_cond_signal(g_threadSendCond);
- }
- else // error
- {
- // update state
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- OIC_LOG(ERROR, TAG, "jni_address is null");
- goto error_exit;
-
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (address)
- {
- CAResult_t res = CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
- STATE_CHARACTER_NO_CHANGE,
- STATE_SEND_FAILED);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
- }
- }
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
-
- CAResult_t res = CALEClientGattClose(env, gatt);
- if (CA_STATUS_OK != res)
+ if (g_sendBuffer)
{
- OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
+ (*env)->DeleteGlobalRef(env, g_sendBuffer);
+ g_sendBuffer = NULL;
}
-
- goto error_exit;
}
return;
error_exit:
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
{
OIC_LOG_V(DEBUG, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
if (0 != status) // discovery error
{
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
if (!jni_address)
{
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
if (!address)
{
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "CALEClientSetUUIDToDescriptor has failed");
- goto error_exit;
+ OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
+ if (g_sendBuffer)
+ {
+ CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+ goto error_exit;
+ }
+ }
}
res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
goto error_exit;
}
}
-
+ OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
(*env)->ReleaseStringUTFChars(env, jni_address, address);
return;
// error label.
error_exit:
+ OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
(*env)->ReleaseStringUTFChars(env, jni_address, address);
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
/*
* Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattCharacteristicReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicReadCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jobject characteristic,
- jbyteArray data,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicReadCallback - status : %d", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
* Method: CALeGattCharacteristicWritjclasseCallback
* Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
- JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data,
+ JNIEnv *env, jobject obj, jobject gatt, jbyteArray data,
jint status)
{
OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
- ca_mutex_lock(g_threadSendCBMutex);
- if (!g_isRequestedSend)
- {
- OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicWriteCallback - waiting");
- ca_cond_wait(g_threadSendCBCond, g_threadSendCBMutex);
- }
- ca_mutex_unlock(g_threadSendCBMutex);
-
jboolean isCopy;
char* wroteData = (char*) (*env)->GetByteArrayElements(env, data, &isCopy);
goto error_exit;
}
- if (GATT_SUCCESS != status) // error case
+ jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+ if (gatt_success != status) // error case
{
OIC_LOG(ERROR, TAG, "send failure");
- CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
- STATE_SEND_FAILED);
+
+ // retry to write
+ CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
if (CA_STATUS_OK != res)
{
- OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+ OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
+ ca_mutex_lock(g_threadWriteCharacteristicMutex);
+ g_isSignalSetFlag = true;
+ ca_cond_signal(g_threadWriteCharacteristicCond);
+ ca_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+ CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
+ STATE_CHARACTER_SET,
+ STATE_SEND_FAILED);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+ }
+
+ if (g_clientErrorCallback)
+ {
+ jint length = (*env)->GetArrayLength(env, data);
+ g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
+ }
+
+ CALEClientSendFinish(env, gatt);
+ goto error_exit;
}
- CALEClientSendFinish(env, gatt);
}
else
{
{
OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
}
+
+ ca_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);
+
CALEClientUpdateSendCnt(env);
}
- CALEClientSetWriteCharacteristicCBFlag(true);
- CALEClientSetTheSendRequestFlag(false);
- ca_cond_signal(g_threadSendCond);
(*env)->ReleaseStringUTFChars(env, jni_address, address);
return;
// error label.
error_exit:
- CALEClientSetWriteCharacteristicCBFlag(true);
- CALEClientSetTheSendRequestFlag(false);
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
- JNIEnv *env, jobject obj, jobject gatt, jobject characteristic, jbyteArray data)
+ JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
{
OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback");
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
VERIFY_NON_NULL_VOID(data, TAG, "data is null");
- // get Byte Array and covert to char*
+ // get Byte Array and convert to uint8_t*
jint length = (*env)->GetArrayLength(env, data);
jboolean isCopy;
jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %s",
+ OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
jni_byte_responseData);
- char* receivedData = (char*) OICMalloc(sizeof(char) * length + 1);
+ uint8_t* receivedData = OICMalloc(length);
if (!receivedData)
{
- OIC_LOG(ERROR, TAG, "recevicedData is null");
+ OIC_LOG(ERROR, TAG, "receivedData is null");
return;
}
- memcpy(receivedData, (const char*) jni_byte_responseData, length);
- receivedData[length] = '\0';
+ memcpy(receivedData, jni_byte_responseData, length);
(*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
return;
}
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %s, %d",
+ OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
receivedData, length);
ca_mutex_lock(g_bleServerBDAddressMutex);
uint32_t sentLength = 0;
- g_CABLEClientDataReceivedCallback(address, OIC_GATT_SERVICE_UUID, receivedData, length,
+ g_CABLEClientDataReceivedCallback(address, receivedData, length,
&sentLength);
ca_mutex_unlock(g_bleServerBDAddressMutex);
/*
* Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattDescriptorReadCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorReadCallback(JNIEnv *env, jobject obj,
- jobject gatt,
- jobject descriptor,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorReadCallback - status %d: ", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
* Method: CALeGattDescriptorWriteCallback
* Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
*/
JNIEXPORT void JNICALL
Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
- jobject gatt,
- jobject descriptor,
- jint status)
+ jobject gatt,
+ jint status)
{
OIC_LOG_V(DEBUG, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
- CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
- if (CA_STATUS_OK != res)
+ jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
+ if (gatt_success != status) // error
{
- OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
goto error_exit;
}
+
+ if (g_sendBuffer)
+ {
+ CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+ goto error_exit;
+ }
+ }
return;
// error label.
error_exit:
CALEClientSendFinish(env, gatt);
- ca_cond_signal(g_threadSendCond);
return;
}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattReliableWriteCompletedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattReliableWriteCompletedCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattReliableWriteCompletedCallback - status %d: ", status);
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattReadRemoteRssiCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattReadRemoteRssiCallback(JNIEnv *env, jobject obj,
- jobject gatt, jint rssi,
- jint status)
-{
- OIC_LOG_V(DEBUG, TAG, "CALeGattReadRemoteRssiCallback - rssi %d, status %d: ", rssi, status);
-}