#include "octhread.h"
#include "uarraylist.h"
#include "org_iotivity_ca_CaLeClientInterface.h"
+#include "caleclient_utils.h"
//#define TAG PCF("OIC_CA_LE_CLIENT")
#define TAG BLE_CLIENT_TAG
JavaVM *g_jvm;
static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
static u_arraylist_t *g_gattObjectList = NULL;
-static u_arraylist_t *g_deviceStateList = NULL;
static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
-static CABLEErrorHandleCallback g_clientErrorCallback;
-static jobject g_leScanCallback = NULL;
-static jobject g_leGattCallback = NULL;
static jobject g_context = NULL;
static jobjectArray g_uuidList = NULL;
// it will be prevent to start send logic when adapter has stopped.
static bool g_isStartedLEClient = false;
-static jbyteArray g_sendBuffer = NULL;
static uint32_t g_targetCnt = 0;
static uint32_t g_currentSentCnt = 0;
static bool g_isFinishedSendData = false;
static oc_cond g_deviceDescCond = NULL;
static oc_mutex g_threadSendMutex = NULL;
-static oc_mutex g_threadWriteCharacteristicMutex = NULL;
-static oc_cond g_threadWriteCharacteristicCond = NULL;
-static bool g_isSignalSetFlag = false;
-
-static oc_mutex g_bleServerBDAddressMutex = NULL;
static oc_mutex g_deviceListMutex = NULL;
static oc_mutex g_gattObjectMutex = NULL;
-static oc_mutex g_deviceStateListMutex = NULL;
static oc_mutex g_deviceScanRetryDelayMutex = NULL;
static oc_cond g_deviceScanRetryDelayCond = NULL;
static CALEScanState_t g_curScanningStep = BLE_SCAN_NONE;
static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE;
-static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
static int32_t g_jniIntSdk = -1;
static bool g_setHighQoS = true;
// List of Manufacture Data
static u_arraylist_t* g_manufactureDataList = NULL;
+//Variables are defined as extern in other file so using it as non-static here
+u_arraylist_t *g_deviceStateList = NULL;
+oc_mutex g_deviceStateListMutex = NULL;
+
+oc_mutex g_threadWriteCharacteristicMutex = NULL;
+oc_cond g_threadWriteCharacteristicCond = NULL;
+oc_mutex g_bleServerBDAddressMutex = NULL;
+
+CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
+
+jobject g_leScanCallback = NULL;
+jobject g_leGattCallback = NULL;
+
+bool g_isSignalSetFlag = false;
+
+jbyteArray g_sendBuffer = NULL;
+
+CABLEErrorHandleCallback g_clientErrorCallback = NULL;
+
/**
* check if retry logic for connection routine has to be stopped or not.
* in case of error value including this method, connection routine has to be stopped.
* @return true - waiting for background connection in BT platform.
* false - connection routine has to be stopped.
*/
-static bool CALECheckConnectionStateValue(jint state)
+bool CALECheckConnectionStateValue(jint state)
{
switch(state)
{
VERIFY_NON_NULL(local_address, TAG, "local_address");
return CA_NOT_SUPPORTED;
}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
- jobject callback)
-{
- 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);
- CACheckJNIException(env);
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
- jobject obj,
- jobject callback)
-{
- OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
- 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);
- CACheckJNIException(env);
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
- jobject 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);
- CACheckJNIException(env);
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
- 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);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
- }
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
- jint errorCode)
-{
- VERIFY_NON_NULL_VOID(env, TAG, "env is null");
- VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
-
- switch (errorCode)
- {
- case 1:
- OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
- break;
-
- case 2:
- OIC_LOG(ERROR, TAG,
- "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
- break;
-
- case 3:
- OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
- break;
-
- case 4:
- OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
- break;
-
- default:
- OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
- break;
- }
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattConnectionStateChangeCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jint status,
- jint newstate)
-{
- OIC_LOG_V(INFO, 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");
-
- jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
-
- 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)
- {
- OIC_LOG(ERROR, TAG, "address is null");
- CACheckJNIException(env);
- goto error_exit;
- }
- OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
-
- if (state_connected == newstate)
- {
- OIC_LOG(DEBUG, TAG, "LE is connected");
- if (GATT_SUCCESS == status)
- {
- CAResult_t res = CALEUpdateDeviceState(address,
- CA_LE_CONNECTION_STATE,
- STATE_CONNECTED,
- g_deviceStateList,
- g_deviceStateListMutex);
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- goto error_exit;
- }
-
- res = CALEClientAddGattobjToList(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
- goto error_exit;
- }
-
- res = CALEClientDiscoverServices(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
- goto error_exit;
- }
- }
- else
- {
- OIC_LOG(INFO, TAG, "unknown status");
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- }
- }
- else // STATE_DISCONNECTED == newstate
- {
- OIC_LOG(DEBUG, TAG, "LE is disconnected");
-
- if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING,
- g_deviceStateList, g_deviceStateListMutex))
- {
- OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING");
- CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
- STATE_SEND_FAIL,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- }
- }
-
- CAResult_t res = CALEUpdateDeviceState(address,
- CA_LE_CONNECTION_STATE,
- STATE_DISCONNECTED,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- }
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
-
- res = CALEClientGattClose(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
- }
-
- if (CALECheckConnectionStateValue(status))
- {
- // this state is unexpected reason to disconnect
- // if the reason is suitable, connection logic of the device will be destroyed.
- OIC_LOG(INFO, TAG, "connection logic destroy");
- }
- else
- {
- // other reason except for gatt_success is expected to running
- // background connection in BT platform.
- OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
- }
- CALEClientUpdateSendCnt(env);
- }
- return;
-
- // error label.
-error_exit:
- CALEClientSendFinish(env, gatt);
- return;
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattServicesDiscoveredCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jint status)
-{
- OIC_LOG_V(INFO, 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 (GATT_SUCCESS != status) // discovery error
- {
- CALEClientSendFinish(env, gatt);
- return;
- }
-
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- CALEClientSendFinish(env, gatt);
- return;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
- {
- CACheckJNIException(env);
- CALEClientSendFinish(env, gatt);
- return;
- }
-
- jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
- if (!jni_uuid)
- {
- OIC_LOG(ERROR, TAG, "jni_uuid is null");
- goto error_exit;
- }
-
- jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
- if (!jni_obj_GattCharacteristic)
- {
- OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
- goto error_exit;
- }
-
- CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
- jni_obj_GattCharacteristic);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
- goto error_exit;
- }
-
- res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
-
- res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE,
- g_deviceStateList, g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
- goto error_exit;
- }
-
- res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
- STATE_SERVICE_CONNECTED,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- goto error_exit;
- }
-
- res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
- goto error_exit;
- }
- }
- else
- {
- res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE,
- g_deviceStateList, g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
- goto error_exit;
- }
- }
-
-#ifdef SCAN_INTERVAL
- // reset interval scan logic
- CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
-#endif
-
- 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);
- return;
-}
-
-/*
- * 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, jbyteArray data, jint status)
-{
- OIC_LOG_V(INFO, 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");
-
- // send success & signal
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- goto error_exit;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
- {
- CACheckJNIException(env);
- goto error_exit;
- }
-
- if (GATT_SUCCESS != status) // error case
- {
- OIC_LOG(ERROR, TAG, "send failure");
-
- // retry to write
- CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
- oc_mutex_lock(g_threadWriteCharacteristicMutex);
- g_isSignalSetFlag = true;
- oc_cond_signal(g_threadWriteCharacteristicCond);
- oc_mutex_unlock(g_threadWriteCharacteristicMutex);
-
- CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
- STATE_SEND_FAIL,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- }
-
- if (g_clientErrorCallback)
- {
- jint length = (*env)->GetArrayLength(env, data);
- CACheckJNIException(env);
- g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
- CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length,
- false, "writeChar failure");
- }
-
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- goto error_exit;
- }
- }
- else
- {
- OIC_LOG(DEBUG, TAG, "send success");
- CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
- STATE_SEND_SUCCESS,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- }
-
- oc_mutex_lock(g_threadWriteCharacteristicMutex);
- OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
- g_isSignalSetFlag = true;
- oc_cond_signal(g_threadWriteCharacteristicCond);
- oc_mutex_unlock(g_threadWriteCharacteristicMutex);
-
- CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0,
- (*env)->GetArrayLength(env, data),
- true, "writeChar success");
- }
-
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- return;
-
- // error label.
-error_exit:
-
- CALEClientSendFinish(env, gatt);
- return;
-}
-
-/*
- * Class: org_iotivity_ca_jar_caleinterface
- * Method: CALeGattCharacteristicChangedCallback
- * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
- */
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
- 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 convert to uint8_t*
- jint length = (*env)->GetArrayLength(env, data);
-
- jboolean isCopy;
- jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
- CACheckJNIException(env);
-
- uint8_t* receivedData = OICMalloc(length);
- if (!receivedData)
- {
- OIC_LOG(ERROR, TAG, "receivedData is null");
- return;
- }
-
- memcpy(receivedData, jni_byte_responseData, length);
- (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
-
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- OIC_LOG(ERROR, TAG, "jni_address is null");
- OICFree(receivedData);
- return;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
- {
- OIC_LOG(ERROR, TAG, "address is null");
- CACheckJNIException(env);
- OICFree(receivedData);
- return;
- }
-
- OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
- receivedData, length);
-
- uint32_t sentLength = 0;
- oc_mutex_lock(g_bleServerBDAddressMutex);
- g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
- oc_mutex_unlock(g_bleServerBDAddressMutex);
-
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
-}
-
-/*
- * 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,
- jint status)
-{
- OIC_LOG_V(INFO, 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");
-
- if (GATT_SUCCESS != status) // error
- {
- goto error_exit;
- }
-
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- goto error_exit;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
- {
- CACheckJNIException(env);
- goto error_exit;
- }
-
- CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
- STATE_SERVICE_CONNECTED,
- g_deviceStateList,
- g_deviceStateListMutex);
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- goto error_exit;
- }
-
- res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
- goto error_exit;
- }
- return;
-
-// error label.
-error_exit:
-
- CALEClientSendFinish(env, gatt);
- return;
-}
-
-JNIEXPORT void JNICALL
-Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env,
- jobject obj,
- jobject gatt,
- jint mtu,
- jint status)
-{
- OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, "
- "mtu[%d-including Header size 3 byte]", status, mtu);
-
- (void)obj;
-
- if (0 == status || 133 == status)
- {
- if (g_sendBuffer)
- {
- CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
- }
- }
- else
- {
- OIC_LOG(INFO, TAG, "mtu nego is done");
- jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
- if (!jni_address)
- {
- CALEClientSendFinish(env, gatt);
- return;
- }
-
- const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
- if (!address)
- {
- CACheckJNIException(env);
- (*env)->DeleteLocalRef(env, jni_address);
- CALEClientSendFinish(env, gatt);
- return;
- }
-
- // update mtu size
- CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE,
- g_deviceStateList, g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed");
- }
-
- res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
- STATE_SEND_MTU_NEGO_SUCCESS,
- g_deviceStateList,
- g_deviceStateListMutex);
- if (CA_STATUS_OK != res)
- {
- OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
- }
- CALEClientUpdateSendCnt(env);
- (*env)->ReleaseStringUTFChars(env, jni_address, address);
- (*env)->DeleteLocalRef(env, jni_address);
- }
- }
-}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2014 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <jni.h>
+#include <unistd.h>
+
+#include "calestate.h"
+#include "caleclient.h"
+#include "caleserver.h"
+#include "caleutils.h"
+#include "caleinterface.h"
+#include "caadapterutils.h"
+
+#include "uarraylist.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cathreadpool.h" /* for thread pool */
+#include "octhread.h"
+#include "uarraylist.h"
+#include "org_iotivity_ca_CaLeClientInterface.h"
+#include "caleclient_utils.h"
+#include "caleclient.h"
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
+ jobject callback)
+{
+ 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);
+ CACheckJNIException(env);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env,
+ jobject obj,
+ jobject callback)
+{
+ OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21");
+ 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);
+ CACheckJNIException(env);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
+ jobject 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);
+ CACheckJNIException(env);
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
+ 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);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj,
+ jint errorCode)
+{
+ VERIFY_NON_NULL_VOID(env, TAG, "env is null");
+ VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
+
+ switch (errorCode)
+ {
+ case 1:
+ OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED");
+ break;
+
+ case 2:
+ OIC_LOG(ERROR, TAG,
+ "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED");
+ break;
+
+ case 3:
+ OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR");
+ break;
+
+ case 4:
+ OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED");
+ break;
+
+ default:
+ OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error");
+ break;
+ }
+}
+
+/*
+ * Class: org_iotivity_ca_jar_caleinterface
+ * Method: CALeGattConnectionStateChangeCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
+ jobject obj,
+ jobject gatt,
+ jint status,
+ jint newstate)
+{
+ OIC_LOG_V(INFO, 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");
+
+ jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
+
+ 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)
+ {
+ OIC_LOG(ERROR, TAG, "address is null");
+ CACheckJNIException(env);
+ goto error_exit;
+ }
+ OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
+
+ if (state_connected == newstate)
+ {
+ OIC_LOG(DEBUG, TAG, "LE is connected");
+ if (GATT_SUCCESS == status)
+ {
+ CAResult_t res = CALEUpdateDeviceState(address,
+ CA_LE_CONNECTION_STATE,
+ STATE_CONNECTED,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ goto error_exit;
+ }
+
+ res = CALEClientAddGattobjToList(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
+ goto error_exit;
+ }
+
+ res = CALEClientDiscoverServices(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
+ goto error_exit;
+ }
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "unknown status");
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ }
+ }
+ else // STATE_DISCONNECTED == newstate
+ {
+ OIC_LOG(DEBUG, TAG, "LE is disconnected");
+
+ if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING,
+ g_deviceStateList, g_deviceStateListMutex))
+ {
+ OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING");
+ CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
+ STATE_SEND_FAIL,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ }
+ }
+
+ CAResult_t res = CALEUpdateDeviceState(address,
+ CA_LE_CONNECTION_STATE,
+ STATE_DISCONNECTED,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ }
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+
+ res = CALEClientGattClose(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
+ }
+
+ if (CALECheckConnectionStateValue(status))
+ {
+ // this state is unexpected reason to disconnect
+ // if the reason is suitable, connection logic of the device will be destroyed.
+ OIC_LOG(INFO, TAG, "connection logic destroy");
+ }
+ else
+ {
+ // other reason except for gatt_success is expected to running
+ // background connection in BT platform.
+ OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
+ }
+ CALEClientUpdateSendCnt(env);
+ }
+ return;
+
+ // error label.
+error_exit:
+ CALEClientSendFinish(env, gatt);
+ return;
+}
+
+/*
+ * Class: org_iotivity_ca_jar_caleinterface
+ * Method: CALeGattServicesDiscoveredCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
+ jobject obj,
+ jobject gatt,
+ jint status)
+{
+ OIC_LOG_V(INFO, 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 (GATT_SUCCESS != status) // discovery error
+ {
+ CALEClientSendFinish(env, gatt);
+ return;
+ }
+
+ jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+ if (!jni_address)
+ {
+ CALEClientSendFinish(env, gatt);
+ return;
+ }
+
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ CACheckJNIException(env);
+ CALEClientSendFinish(env, gatt);
+ return;
+ }
+
+ jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
+ if (!jni_uuid)
+ {
+ OIC_LOG(ERROR, TAG, "jni_uuid is null");
+ goto error_exit;
+ }
+
+ jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
+ if (!jni_obj_GattCharacteristic)
+ {
+ OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
+ goto error_exit;
+ }
+
+ CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
+ jni_obj_GattCharacteristic);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
+ goto error_exit;
+ }
+
+ res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
+
+ res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE,
+ g_deviceStateList, g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
+ goto error_exit;
+ }
+
+ res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
+ STATE_SERVICE_CONNECTED,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ goto error_exit;
+ }
+
+ res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
+ goto error_exit;
+ }
+ }
+ else
+ {
+ res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE,
+ g_deviceStateList, g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed");
+ goto error_exit;
+ }
+ }
+
+#ifdef SCAN_INTERVAL
+ // reset interval scan logic
+ CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
+#endif
+
+ 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);
+ return;
+}
+
+/*
+ * 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, jbyteArray data, jint status)
+{
+ OIC_LOG_V(INFO, 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");
+
+ // send success & signal
+ jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+ if (!jni_address)
+ {
+ goto error_exit;
+ }
+
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ CACheckJNIException(env);
+ goto error_exit;
+ }
+
+ if (GATT_SUCCESS != status) // error case
+ {
+ OIC_LOG(ERROR, TAG, "send failure");
+
+ // retry to write
+ CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
+ oc_mutex_lock(g_threadWriteCharacteristicMutex);
+ g_isSignalSetFlag = true;
+ oc_cond_signal(g_threadWriteCharacteristicCond);
+ oc_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+ CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
+ STATE_SEND_FAIL,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ }
+
+ if (g_clientErrorCallback)
+ {
+ jint length = (*env)->GetArrayLength(env, data);
+ CACheckJNIException(env);
+ g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
+ CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length,
+ false, "writeChar failure");
+ }
+
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ goto error_exit;
+ }
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TAG, "send success");
+ CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
+ STATE_SEND_SUCCESS,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ }
+
+ oc_mutex_lock(g_threadWriteCharacteristicMutex);
+ OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
+ g_isSignalSetFlag = true;
+ oc_cond_signal(g_threadWriteCharacteristicCond);
+ oc_mutex_unlock(g_threadWriteCharacteristicMutex);
+
+ CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0,
+ (*env)->GetArrayLength(env, data),
+ true, "writeChar success");
+ }
+
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ return;
+
+ // error label.
+error_exit:
+
+ CALEClientSendFinish(env, gatt);
+ return;
+}
+
+/*
+ * Class: org_iotivity_ca_jar_caleinterface
+ * Method: CALeGattCharacteristicChangedCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
+ 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 convert to uint8_t*
+ jint length = (*env)->GetArrayLength(env, data);
+
+ jboolean isCopy;
+ jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
+ CACheckJNIException(env);
+
+ uint8_t* receivedData = OICMalloc(length);
+ if (!receivedData)
+ {
+ OIC_LOG(ERROR, TAG, "receivedData is null");
+ return;
+ }
+
+ memcpy(receivedData, jni_byte_responseData, length);
+ (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
+
+ jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+ if (!jni_address)
+ {
+ OIC_LOG(ERROR, TAG, "jni_address is null");
+ OICFree(receivedData);
+ return;
+ }
+
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ OIC_LOG(ERROR, TAG, "address is null");
+ CACheckJNIException(env);
+ OICFree(receivedData);
+ return;
+ }
+
+ OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
+ receivedData, length);
+
+ uint32_t sentLength = 0;
+ oc_mutex_lock(g_bleServerBDAddressMutex);
+ g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
+ oc_mutex_unlock(g_bleServerBDAddressMutex);
+
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+}
+
+/*
+ * 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,
+ jint status)
+{
+ OIC_LOG_V(INFO, 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");
+
+ if (GATT_SUCCESS != status) // error
+ {
+ goto error_exit;
+ }
+
+ jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+ if (!jni_address)
+ {
+ goto error_exit;
+ }
+
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ CACheckJNIException(env);
+ goto error_exit;
+ }
+
+ CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
+ STATE_SERVICE_CONNECTED,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ goto error_exit;
+ }
+
+ res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
+ goto error_exit;
+ }
+ return;
+
+// error label.
+error_exit:
+
+ CALEClientSendFinish(env, gatt);
+ return;
+}
+
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env,
+ jobject obj,
+ jobject gatt,
+ jint mtu,
+ jint status)
+{
+ OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, "
+ "mtu[%d-including Header size 3 byte]", status, mtu);
+
+ (void)obj;
+
+ if (0 == status || 133 == status)
+ {
+ if (g_sendBuffer)
+ {
+ CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
+ }
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "mtu nego is done");
+ jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
+ if (!jni_address)
+ {
+ CALEClientSendFinish(env, gatt);
+ return;
+ }
+
+ const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
+ if (!address)
+ {
+ CACheckJNIException(env);
+ (*env)->DeleteLocalRef(env, jni_address);
+ CALEClientSendFinish(env, gatt);
+ return;
+ }
+
+ // update mtu size
+ CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE,
+ g_deviceStateList, g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed");
+ }
+
+ res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE,
+ STATE_SEND_MTU_NEGO_SUCCESS,
+ g_deviceStateList,
+ g_deviceStateListMutex);
+ if (CA_STATUS_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed");
+ }
+ CALEClientUpdateSendCnt(env);
+ (*env)->ReleaseStringUTFChars(env, jni_address, address);
+ (*env)->DeleteLocalRef(env, jni_address);
+ }
+ }
+}