To support MTU negotiation for BLE (android client to tizen server) 75/16275/14
authorjihwan.seo <jihwan.seo@samsung.com>
Fri, 30 Dec 2016 03:26:51 +0000 (12:26 +0900)
committerAshok Babu Channa <ashok.channa@samsung.com>
Mon, 23 Jan 2017 14:33:53 +0000 (14:33 +0000)
Android to Android, Tizen to Tizen will be supported by next patch.

Change-Id: I736724df83c57a2193ab591bd7463dd2368642ea
Signed-off-by: jihwan.seo <jihwan.seo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/16275
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: MyeongGi Jeong <myeong.jeong@samsung.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
17 files changed:
java/iotivity-android/src/main/java/org/iotivity/ca/CaLeClientInterface.java
java/iotivity-android/src/main/java/org/iotivity/ca/CaLeServerInterface.java
resource/csdk/connectivity/inc/cafragmentation.h
resource/csdk/connectivity/inc/caleinterface.h
resource/csdk/connectivity/src/adapter_util/cafragmentation.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h
resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.h
resource/csdk/connectivity/src/bt_le_adapter/android/org_iotivity_ca_CaLeClientInterface.h
resource/csdk/connectivity/src/bt_le_adapter/android/org_iotivity_ca_CaLeServerInterface.h
resource/csdk/connectivity/src/bt_le_adapter/caleadapter.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleclient.h
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.c
resource/csdk/connectivity/src/bt_le_adapter/tizen/caleserver.h
resource/csdk/connectivity/test/ca_api_unittest.cpp

index 695359b..3984992 100644 (file)
@@ -132,6 +132,9 @@ public class CaLeClientInterface {
     private native static void caManagerLeRemoteRssiCallback(BluetoothGatt gatt, int rssi,
                                                              int status);
 
+    private native static void caLeGattMtuChangedCallback(BluetoothGatt gatt, int mtu,
+                                                          int status);
+
     // Callback
     private static BluetoothAdapter.LeScanCallback mLeScanCallback =
                    new BluetoothAdapter.LeScanCallback() {
@@ -270,6 +273,12 @@ public class CaLeClientInterface {
             super.onReadRemoteRssi(gatt, rssi, status);
             caManagerLeRemoteRssiCallback(gatt, rssi, status);
         }
+
+        @Override
+        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
+            super.onMtuChanged(gatt, mtu, status);
+            caLeGattMtuChangedCallback(gatt, mtu, status);
+        }
     };
 
     private static final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -312,4 +321,3 @@ public class CaLeClientInterface {
     };
 }
 
-
index 48c5b6b..cc5185b 100644 (file)
@@ -67,6 +67,8 @@ public class CaLeServerInterface {
     private native static void caLeGattServerNotificationSentCallback(BluetoothDevice device,
                                                                      int status);
 
+    private native static void caLeGattServerMtuChangedCallback(BluetoothDevice gatt, int mtu);
+
     // AdvertiseCallback
     private native static void caLeAdvertiseStartSuccessCallback(
             AdvertiseSettings settingsInEffect);
index aa10eb0..72ad7b5 100644 (file)
 #include "cacommon.h"
 #include "logger.h"
 
-/**
- * The MTU supported for BLE adapter
- */
-#define CA_SUPPORTED_BLE_MTU_SIZE  20
-
 /**
  * The maximum port value for BLE packet format
  */
  */
 #define CA_BLE_LENGTH_HEADER_SIZE 4
 
-/**
- * The length payload size of the normal data segment (after first segment) for ble fragmentation.
- */
-#define CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE ((CA_SUPPORTED_BLE_MTU_SIZE) \
-                                            - (CA_BLE_HEADER_SIZE))
-
-/**
- * The length payload size of the first data segment for ble fragmentation.
- */
-#define CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE ((CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE) \
-                                           - (CA_BLE_LENGTH_HEADER_SIZE))
-
 /**
  * Current Header version.
  */
@@ -130,6 +113,7 @@ typedef enum {
  *                              packet.
  * @param[out]  remainingLen    Size of last packet before adding header.
  * @param[out]  totalLengh      The total length of the data.
+ * @param[in]   mtuSize         MTU size.
  *
  * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
  *           or other error values on error.
@@ -139,7 +123,8 @@ typedef enum {
 CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
                                               uint32_t *midPacketCount,
                                               size_t *remainingLen,
-                                              size_t *totalLength);
+                                              size_t *totalLength,
+                                              uint16_t mtuSize);
 
 /**
  * This function is used to generate the CA BLE header to
@@ -237,6 +222,7 @@ CAResult_t CAMakeFirstDataSegment(uint8_t *dataSegment,
  *                                     total data
  * @param[in]   dataHeader             Pointer to the octet array that contain
  *                                     data header.
+ * @param[in]   mtuSize                MTU size.
  *
  * @return ::CA_STATUS_OK on success. One of the CA_STATUS_FAILED
  *           or other error values on error.
@@ -249,7 +235,8 @@ CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
                                    const uint8_t *sourceData,
                                    const uint32_t sourceDataLength,
                                    const uint32_t segmentNum,
-                                   const uint8_t *dataHeader);
+                                   const uint8_t *dataHeader,
+                                   uint16_t mtuSize);
 
 /**
  * This function is used to parse the header in the receiver end. This
index 6e78bc9..af384c4 100644 (file)
@@ -71,6 +71,21 @@ typedef struct
     u_arraylist_t * senderInfo;
 } CALEData_t;
 
+/**
+ * The MTU supported for BLE adapter
+ */
+#define CA_DEFAULT_BLE_MTU_SIZE  20
+
+/**
+ * The MTU supported for BLE spec
+ */
+#define CA_SUPPORTED_BLE_MTU_SIZE  517
+
+/**
+ * The Header of the MTU supported for BLE spec
+ */
+#define CA_BLE_MTU_HEADER_SIZE  3
+
 /**
  * This will be used to notify device status changes to the LE adapter layer.
  * @param[in]  adapter_state State of the adapter.
index 859728e..9b0bee2 100644 (file)
@@ -24,6 +24,7 @@
 #include "cacommon.h"
 #include "caadapterutils.h"
 #include "cafragmentation.h"
+#include "caleinterface.h"
 
 /**
  * Debugging tag for fragmentation module.
@@ -82,13 +83,14 @@ static uint8_t CAGetBits(uint8_t x, unsigned p, unsigned n)
 CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
                                               uint32_t *midPacketCount,
                                               size_t *remainingLen,
-                                              size_t *totalLength)
+                                              size_t *totalLength,
+                                              uint16_t mtuSize)
 {
-    OIC_LOG_V(DEBUG, TAG, "IN, dataLength = %zu", dataLength);
+    OIC_LOG_V(DEBUG, TAG, "IN, dataLength = %zu, mtu = %zu", dataLength, mtuSize);
 
     size_t remainDataSize = 0;
     size_t dataOnlyLen =
-        CA_SUPPORTED_BLE_MTU_SIZE - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
+            mtuSize - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
     //total data size is smaller than 14 byte case.
     if (dataLength < dataOnlyLen)
     {
@@ -99,14 +101,14 @@ CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
         remainDataSize = dataLength - dataOnlyLen;
     }
 
-    if (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE <= 0)
+    if (mtuSize - CA_BLE_HEADER_SIZE <= 0)
     {
         OIC_LOG_V(ERROR, TAG, "BLE header size shouldn't be bigger than BLE MTU size.");
         return CA_STATUS_FAILED;
     }
 
-    *midPacketCount = (uint32_t)remainDataSize / (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
-    *remainingLen = (uint32_t)remainDataSize % (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
+    *midPacketCount = (uint32_t)remainDataSize / (mtuSize - CA_BLE_HEADER_SIZE);
+    *remainingLen = (uint32_t)remainDataSize % (mtuSize - CA_BLE_HEADER_SIZE);
     uint32_t remainHeaderSize = CA_BLE_HEADER_SIZE * (*midPacketCount + (*remainingLen == 0 ? 0:1));
     *totalLength = dataLength + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE) + remainHeaderSize;
 
@@ -189,15 +191,16 @@ CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
                                    const uint8_t *sourceData,
                                    const uint32_t sourceDataLength,
                                    const uint32_t segmentNum,
-                                   const uint8_t *dataHeader)
+                                   const uint8_t *dataHeader,
+                                   uint16_t mtuSize)
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
 
-    uint32_t index = CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE +
-            (segmentNum * CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE);
+    uint32_t index = (mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE) +
+            (segmentNum * (mtuSize - CA_BLE_HEADER_SIZE));
     if (sourceDataLength < index + segmentPayloadLength)
     {
         OIC_LOG(DEBUG, TAG, "dataSegment will exceed");
index 62cd60a..8892970 100644 (file)
@@ -110,6 +110,7 @@ static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE;
 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
 
 static bool g_setHighQoS = true;
+
 /**
  * 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.
@@ -687,6 +688,14 @@ void CALEClientSendFinish(JNIEnv *env, jobject gatt)
     CALEClientUpdateSendCnt(env);
 }
 
+CAResult_t CALEClientSendNegotiationMessage(const char* address)
+{
+    OIC_LOG_V(DEBUG, TAG, "CALEClientSendNegotiationMessage(%s)", address);
+    VERIFY_NON_NULL(address, TAG, "address is null");
+
+    return CALEClientSendUnicastMessageImpl(address, NULL, 0);
+}
+
 CAResult_t CALEClientSendUnicastMessage(const char* address,
                                         const uint8_t* data,
                                         const uint32_t dataLen)
@@ -876,7 +885,6 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t*
     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");
 
     if (!g_jvm)
     {
@@ -949,12 +957,16 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t*
                     (*env)->DeleteGlobalRef(env, g_sendBuffer);
                     g_sendBuffer = NULL;
                 }
-                jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
-                CACheckJNIException(env);
-                (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
-                CACheckJNIException(env);
-                g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
-                CACheckJNIException(env);
+
+                if (data && dataLen > 0)
+                {
+                    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+                    CACheckJNIException(env);
+                    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+                    CACheckJNIException(env);
+                    g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+                    CACheckJNIException(env);
+                }
 
                 // Target device to send message is just one.
                 g_targetCnt = 1;
@@ -1000,6 +1012,12 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t*
         OIC_LOG(INFO, TAG, "send success");
         ret = CA_STATUS_OK;
     }
+    else if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
+                                    STATE_SEND_MTU_NEGO_SUCCESS))
+    {
+        OIC_LOG(INFO, TAG, "mtu nego success");
+        ret = CA_STATUS_OK;
+    }
     else
     {
         OIC_LOG(ERROR, TAG, "send failure");
@@ -1958,6 +1976,18 @@ jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean aut
     return jni_obj_connectGatt;
 }
 
+bool CALEClientIsConnected(const char* address)
+{
+    if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
+                               STATE_SERVICE_CONNECTED))
+    {
+        OIC_LOG(DEBUG, TAG, "current state is connected");
+        return true;
+    }
+    OIC_LOG(DEBUG, TAG, "current state is not connected");
+    return false;
+}
+
 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
 {
     OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
@@ -2170,6 +2200,40 @@ CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
     return CA_STATUS_OK;
 }
 
+CAResult_t CALEClientRequestMTU(JNIEnv *env, jobject bluetoothGatt, jint size)
+{
+    VERIFY_NON_NULL(env, TAG, "env is null");
+    VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
+
+    if (!CALEIsEnableBTAdapter(env))
+    {
+        OIC_LOG(INFO, TAG, "BT adapter is not enabled");
+        return CA_ADAPTER_NOT_ENABLED;
+    }
+
+    // get BluetoothGatt.requestMtu method
+    OIC_LOG(DEBUG, TAG, "get BluetoothGatt.requestMtu method");
+    jmethodID jni_mid_requestMtu = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
+                                                    "requestMtu", "(I)Z");
+    if (!jni_mid_requestMtu)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_requestMtu is null");
+        return CA_STATUS_FAILED;
+    }
+
+    // call requestMtu
+    OIC_LOG(INFO, TAG, "CALL API - requestMtu");
+    jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_requestMtu, size);
+    if (!ret)
+    {
+        OIC_LOG(ERROR, TAG, "requestMtu has failed");
+        CACheckJNIException(env);
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
+}
+
 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
 {
     VERIFY_NON_NULL(env, TAG, "env is null");
@@ -3622,6 +3686,58 @@ CAResult_t CALEClientUpdateDeviceStateWithBtDevice(JNIEnv *env,
     return res;
 }
 
+CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize)
+{
+    VERIFY_NON_NULL(address, TAG, "address is null");
+
+    oc_mutex_lock(g_deviceStateListMutex);
+    if (CALEClientIsDeviceInList(address))
+    {
+        CALEState_t* curState = CALEClientGetStateInfo(address);
+        if(!curState)
+        {
+            OIC_LOG(ERROR, TAG, "curState is null");
+            oc_mutex_unlock(g_deviceStateListMutex);
+            return CA_STATUS_FAILED;
+        }
+
+        curState->mtuSize = mtuSize;
+        OIC_LOG_V(INFO, TAG, "update state - addr: %s, mtu: %d",
+                  curState->address, curState->mtuSize);
+    }
+    else
+    {
+        OIC_LOG(ERROR, TAG, "there is no state info in the list");
+    }
+    oc_mutex_unlock(g_deviceStateListMutex);
+    return CA_STATUS_OK;
+}
+
+uint16_t CALEClientGetMtuSize(const char* address)
+{
+    VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
+
+    oc_mutex_lock(g_deviceStateListMutex);
+    if (CALEClientIsDeviceInList(address))
+    {
+        CALEState_t* curState = CALEClientGetStateInfo(address);
+        if(!curState)
+        {
+            OIC_LOG(ERROR, TAG, "curState is null");
+            oc_mutex_unlock(g_deviceStateListMutex);
+            return CA_DEFAULT_BLE_MTU_SIZE;
+        }
+
+        OIC_LOG_V(INFO, TAG, "state - addr: %s, mtu: %d",
+                  curState->address, curState->mtuSize);
+        oc_mutex_unlock(g_deviceStateListMutex);
+        return curState->mtuSize;
+    }
+
+    oc_mutex_unlock(g_deviceStateListMutex);
+    return CA_DEFAULT_BLE_MTU_SIZE;
+}
+
 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
                                        uint16_t target_state)
 {
@@ -3656,9 +3772,9 @@ CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
             default:
                 break;
         }
-        OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
+        OIC_LOG_V(INFO, TAG, "update state - addr: %s, conn: %d, send: %d, ACFlag: %d, mtu: %d",
                   curState->address, curState->connectedState, curState->sendState,
-                  curState->autoConnectFlag);
+                  curState->autoConnectFlag, curState->mtuSize);
     }
     else /** state is added newly **/
     {
@@ -3678,7 +3794,7 @@ CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
         }
 
         OICStrcpy(newstate->address, sizeof(newstate->address), address);
-
+        newstate->mtuSize = CA_DEFAULT_BLE_MTU_SIZE;
         switch(state_type)
         {
             case CA_LE_CONNECTION_STATE:
@@ -4294,7 +4410,6 @@ CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const
                                                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)
@@ -4579,14 +4694,11 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIE
             goto error_exit;
         }
 
-        if (g_sendBuffer)
+        res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE);
+        if (CA_STATUS_OK != res)
         {
-            CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
-            if (CA_STATUS_OK != res)
-            {
-                OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
-                goto error_exit;
-            }
+            OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed");
+            goto error_exit;
         }
     }
     else
@@ -4831,3 +4943,64 @@ 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 - mtu[%d-including Header size 3 byte)", mtu);
+    OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d", status);
+
+    (void)obj;
+
+    if (0 == 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 = CALEClientSetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientSetMtuSize has failed");
+            }
+
+            res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
+                                              STATE_SEND_MTU_NEGO_SUCCESS);
+            if (CA_STATUS_OK != res)
+            {
+                OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
+            }
+            CALEClientUpdateSendCnt(env);
+            (*env)->ReleaseStringUTFChars(env, jni_address, address);
+            (*env)->DeleteLocalRef(env, jni_address);
+        }
+    }
+}
index 8072de9..a9f62d4 100644 (file)
@@ -42,6 +42,7 @@ static const uint16_t STATE_SEND_SUCCESS = 2;
 static const uint16_t STATE_SEND_FAIL = 3;
 static const uint16_t STATE_SENDING = 4;
 static const uint16_t STATE_SEND_PREPARING = 5;
+static const uint16_t STATE_SEND_MTU_NEGO_SUCCESS = 6;
 
 typedef struct le_state_info
 {
@@ -50,6 +51,7 @@ typedef struct le_state_info
     uint16_t sendState;
     jboolean autoConnectFlag;
     jboolean isDescriptorFound;
+    uint16_t mtuSize;
 } CALEState_t;
 
 /**
@@ -110,6 +112,13 @@ CAResult_t CALEClientDestroyJniInterface();
  */
 void CALEClientSendFinish(JNIEnv *env, jobject gatt);
 
+/**
+ * send negotiation message after gatt connection is done.
+ * @param[in]   address               remote address.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientSendNegotiationMessage(const char* address);
+
 /**
  * send data for unicast (interface).
  * @param[in]   address               remote address.
@@ -319,6 +328,14 @@ CAResult_t CALEClientDisconnectAll(JNIEnv *env);
  */
 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remoteAddress);
 
+/**
+ * request MTU size negotiation to server.
+ * @param[in]   env                   JNI interface pointer.
+ * @param[in]   bluetoothGatt         gatt object.
+ * @param[in]   size                  MTU size.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientRequestMTU(JNIEnv *env, jobject bluetoothGatt, jint size);
 /**
  * start discovery server.
  * @param[in]   env                   JNI interface pointer.
@@ -523,6 +540,22 @@ CAResult_t CALEClientUpdateDeviceStateWithBtDevice(JNIEnv *env,
 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
                                        uint16_t target_state);
 
+/**
+ * This function is used to set MTU size
+ * which negotiated between client and server device.
+ * @param[in]   address               remote address.
+ * @param[in]   mtuSize               MTU size.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize);
+
+/**
+ * get MTU size.
+ * @param[in] address      the address of the remote device.
+ * @return  mtu size negotiated from remote device.
+ */
+uint16_t CALEClientGetMtuSize(const char* address);
+
 /**
  * check whether the remote address is existed or not.
  * @param[in]   address               remote address.
@@ -621,6 +654,13 @@ jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean aut
  */
 CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect);
 
+/**
+ * check connection status.
+ * @param[in] address      the address of the remote device.
+ * @return  true or false.
+ */
+bool CALEClientIsConnected(const char* address);
+
 /**
  * set new interval time and working count.
  * @param[in]  intervalTime             interval time(Seconds).
index fe4f2a7..9916e33 100644 (file)
@@ -2582,6 +2582,19 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback(JNIEn
     }
 }
 
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerMtuChangedCallback(JNIEnv * env,
+                                                                          jobject obj,
+                                                                          jobject device,
+                                                                          jint mtu)
+{
+    VERIFY_NON_NULL_VOID(env, TAG, "env");
+    VERIFY_NON_NULL_VOID(obj, TAG, "obj");
+    VERIFY_NON_NULL_VOID(device, TAG, "device");
+
+    OIC_LOG_V(INFO, TAG, "gatt MTU size is changed (%d byte)", mtu);
+}
+
 /**
  * adapter common
  */
@@ -2816,3 +2829,20 @@ void CALEServerTerminateConditionVaraibles()
 {
     OIC_LOG(DEBUG, TAG, "this method is not supported");
 }
+
+bool CALEServerIsConnected(const char* address)
+{
+    //@Todo
+    //it will be implemented next patch.
+    return true;
+}
+
+uint16_t CALEServerGetMtuSize(const char* address)
+{
+    VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
+
+    //@Todo
+    //it will be implemented next patch.
+    return CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_MTU_HEADER_SIZE;
+}
+
index 2854df8..516075e 100644 (file)
@@ -324,6 +324,19 @@ CAResult_t CALEServerInitConditionVaraibles();
  */
 void CALEServerTerminateConditionVaraibles();
 
+/**
+ * check connection status.
+ * @param[in] address      the address of the remote device.
+ * @return  true or false.
+ */
+bool CALEServerIsConnected(const char* address);
+
+/**
+ * get MTU size.
+ * @param[in] address      the address of the remote device.
+ * @return  mtu size negotiated from remote device.
+ */
+uint16_t CALEServerGetMtuSize(const char* address);
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index acfe990..2b9c21c 100644 (file)
@@ -180,6 +180,16 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback
 (JNIEnv *, jobject, jobject, jint, jint);
 
+/*
+ * Class:     org_iotivity_ca_CaLeClientInterface
+ * Method:    caLeGattMtuChangedCallback
+ * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback
+(JNIEnv *, jobject, jobject, jint, jint);
+
+
 #ifdef __cplusplus
 }
 #endif
index b362fc9..904d1a7 100644 (file)
@@ -118,6 +118,14 @@ JNIEXPORT void JNICALL
 Java_org_iotivity_ca_CaLeServerInterface_caLeAdvertiseStartFailureCallback
 (JNIEnv *, jobject, jint);
 
+/*
+ * Class:     org_iotivity_ca_CaLeServerInterface
+ * Method:    caLeGattServerMtuChangedCallback
+ * Signature: (Landroid/bluetooth/BluetoothDevice;I)V
+ */
+JNIEXPORT void JNICALL
+Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerMtuChangedCallback
+(JNIEnv *, jobject, jobject, jint);
 
 #ifdef __cplusplus
 }
index a42c55f..5e86577 100644 (file)
@@ -69,6 +69,11 @@ typedef enum
     ADAPTER_SERVER
 } CABLEAdapter_t;
 
+/**
+ * mtu size to use in fragmentation logic.
+ * default value is 20 byte.
+ */
+static uint16_t g_mtuSize = CA_DEFAULT_BLE_MTU_SIZE;
 /**
  * Callback to provide the status of the network change to CA layer.
  */
@@ -1222,6 +1227,18 @@ static void CALEServerSendDataThread(void *threadData)
         return;
     }
 
+    if (!bleData->remoteEndpoint)
+    {
+        OIC_LOG(ERROR, CALEADAPTER_TAG, "Invalid endpoint of bledata!");
+        return;
+    }
+
+#if defined(__TIZEN__) || defined(__ANDROID__)
+    // get MTU size
+    g_mtuSize = CALEServerGetMtuSize(bleData->remoteEndpoint->addr);
+#endif
+    OIC_LOG_V(INFO, CALEADAPTER_TAG, "MTU size [%d]", g_mtuSize);
+
     uint32_t midPacketCount = 0;
     size_t remainingLen = 0;
     size_t totalLength = 0;
@@ -1230,7 +1247,8 @@ static void CALEServerSendDataThread(void *threadData)
     CAResult_t result = CAGenerateVariableForFragmentation(bleData->dataLen,
                                                            &midPacketCount,
                                                            &remainingLen,
-                                                           &totalLength);
+                                                           &totalLength,
+                                                           g_mtuSize);
 
     if (CA_STATUS_OK != result)
     {
@@ -1296,15 +1314,15 @@ static void CALEServerSendDataThread(void *threadData)
 
     uint32_t length = 0;
     uint32_t dataLen = 0;
-    if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
+    if (g_mtuSize > totalLength)
     {
         length = totalLength;
         dataLen = bleData->dataLen;
     }
     else
     {
-        length = CA_SUPPORTED_BLE_MTU_SIZE;
-        dataLen = CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE;
+        length = g_mtuSize;
+        dataLen = g_mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
     }
 
     result = CAMakeFirstDataSegment(dataSegment,
@@ -1367,11 +1385,12 @@ static void CALEServerSendDataThread(void *threadData)
         {
             // Send the remaining header.
             result = CAMakeRemainDataSegment(dataSegment,
-                                             CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE,
+                                             g_mtuSize - CA_BLE_HEADER_SIZE,
                                              bleData->data,
                                              bleData->dataLen,
                                              index,
-                                             dataHeader);
+                                             dataHeader,
+                                             g_mtuSize);
 
             if (CA_STATUS_OK != result)
             {
@@ -1385,7 +1404,7 @@ static void CALEServerSendDataThread(void *threadData)
                 CAUpdateCharacteristicsToGattClient(
                     bleData->remoteEndpoint->addr,
                     dataSegment,
-                    CA_SUPPORTED_BLE_MTU_SIZE);
+                    g_mtuSize);
 
             if (CA_STATUS_OK != result)
             {
@@ -1394,14 +1413,11 @@ static void CALEServerSendDataThread(void *threadData)
                 g_errorHandler(bleData->remoteEndpoint, bleData->data, bleData->dataLen, result);
                 return;
             }
-            OIC_LOG_V(DEBUG,
-                      CALEADAPTER_TAG,
-                      "Server Sent Unicast %d Data - data length [%zu]",
-                      index + 1,
-                      CA_SUPPORTED_BLE_MTU_SIZE);
+            OIC_LOG_V(DEBUG, CALEADAPTER_TAG, "Server Sent data length [%d]",
+                                               g_mtuSize);
         }
 
-        if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
+        if (remainingLen && (totalLength > g_mtuSize))
         {
             // send the last segment of the data (Ex: 22 bytes of 622
             // bytes of data when MTU is 200)
@@ -1410,7 +1426,8 @@ static void CALEServerSendDataThread(void *threadData)
                                              bleData->data,
                                              bleData->dataLen,
                                              index,
-                                             dataHeader);
+                                             dataHeader,
+                                             g_mtuSize);
 
             if (CA_STATUS_OK != result)
             {
@@ -1566,6 +1583,38 @@ static void CALEClientSendDataThread(void *threadData)
         return;
     }
 
+    if (!bleData->remoteEndpoint)
+    {
+        OIC_LOG(ERROR, CALEADAPTER_TAG, "Invalid endpoint of bledata!");
+        return;
+    }
+
+#if defined(__TIZEN__) || defined(__ANDROID__)
+    // get MTU size
+    if (false == CALEClientIsConnected(bleData->remoteEndpoint->addr))
+    {
+        // triggering to gatt connect and MTU negotiation
+        CAResult_t res = CALEClientSendNegotiationMessage(
+                bleData->remoteEndpoint->addr);
+
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG_V(ERROR,
+                      CALEADAPTER_TAG,
+                      "CALEClientSendNegotiationMessage has failed, result [%d]",
+                      res);
+
+            g_errorHandler(bleData->remoteEndpoint,
+                           bleData->data,
+                           bleData->dataLen,
+                           res);
+            return;
+        }
+    }
+    g_mtuSize = CALEClientGetMtuSize(bleData->remoteEndpoint->addr);
+#endif
+    OIC_LOG_V(INFO, CALEADAPTER_TAG, "MTU size [%d]", g_mtuSize);
+
     uint32_t midPacketCount = 0;
     size_t remainingLen = 0;
     size_t totalLength = 0;
@@ -1574,7 +1623,8 @@ static void CALEClientSendDataThread(void *threadData)
     CAResult_t result = CAGenerateVariableForFragmentation(bleData->dataLen,
                                                            &midPacketCount,
                                                            &remainingLen,
-                                                           &totalLength);
+                                                           &totalLength,
+                                                           g_mtuSize);
 
     if (CA_STATUS_OK != result)
     {
@@ -1635,15 +1685,15 @@ static void CALEClientSendDataThread(void *threadData)
 
     uint32_t length = 0;
     uint32_t dataLen = 0;
-    if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
+    if (g_mtuSize > totalLength)
     {
         length = totalLength;
         dataLen = bleData->dataLen;
     }
     else
     {
-        length = CA_SUPPORTED_BLE_MTU_SIZE;
-        dataLen = CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE;
+        length = g_mtuSize;
+        dataLen = g_mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
     }
 
     result = CAMakeFirstDataSegment(dataSegment,
@@ -1662,7 +1712,7 @@ static void CALEClientSendDataThread(void *threadData)
     uint32_t index = 0;
     if (NULL != bleData->remoteEndpoint) //Sending Unicast Data
     {
-        OIC_LOG(DEBUG, CALEADAPTER_TAG, "Client Sending Unicast Data");
+        OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending Unicast Data");
         // Send the first segment with the header.
         result =
             CAUpdateCharacteristicsToGattServer(
@@ -1706,11 +1756,12 @@ static void CALEClientSendDataThread(void *threadData)
         for (index = 0; index < iter; index++)
         {
             result = CAMakeRemainDataSegment(dataSegment,
-                                             CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE,
+                                             g_mtuSize - CA_BLE_HEADER_SIZE,
                                              bleData->data,
                                              bleData->dataLen,
                                              index,
-                                             dataHeader);
+                                             dataHeader,
+                                             g_mtuSize);
 
             if (CA_STATUS_OK != result)
             {
@@ -1724,7 +1775,7 @@ static void CALEClientSendDataThread(void *threadData)
             result = CAUpdateCharacteristicsToGattServer(
                      bleData->remoteEndpoint->addr,
                      dataSegment,
-                     CA_SUPPORTED_BLE_MTU_SIZE,
+                     g_mtuSize,
                      LE_UNICAST, 0);
 
             if (CA_STATUS_OK != result)
@@ -1738,12 +1789,12 @@ static void CALEClientSendDataThread(void *threadData)
             }
             OIC_LOG_V(DEBUG,
                       CALEADAPTER_TAG,
-                      "Client Sent Unicast %d Data - data length [%zu]",
+                      "Client Sent Unicast %d Data - data(mtu) length [%zu]",
                       index + 1,
-                      CA_SUPPORTED_BLE_MTU_SIZE);
+                      g_mtuSize);
         }
 
-        if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
+        if (remainingLen && (totalLength > g_mtuSize))
         {
             // send the last segment of the data (Ex: 22 bytes of 622
             // bytes of data when MTU is 200)
@@ -1752,7 +1803,8 @@ static void CALEClientSendDataThread(void *threadData)
                                              bleData->data,
                                              bleData->dataLen,
                                              index,
-                                             dataHeader);
+                                             dataHeader,
+                                             g_mtuSize);
 
             if (CA_STATUS_OK != result)
             {
@@ -2085,7 +2137,8 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
     CAResult_t result = CAGenerateVariableForFragmentation(dataLen,
                                                            &midPacketCount,
                                                            &remainingLen,
-                                                           &totalLength);
+                                                           &totalLength,
+                                                           g_mtuSize);
 
     if (CA_STATUS_OK != result)
     {
@@ -2133,15 +2186,15 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
 
     uint32_t length = 0;
     uint32_t dataOnlyLen = 0;
-    if (CA_SUPPORTED_BLE_MTU_SIZE > totalLength)
+    if (g_mtuSize > totalLength)
     {
         length = totalLength;
         dataOnlyLen = dataLen;
     }
     else
     {
-        length = CA_SUPPORTED_BLE_MTU_SIZE;
-        dataOnlyLen = CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE;
+        length = g_mtuSize;
+        dataOnlyLen = g_mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE;
     }
 
     result = CAMakeFirstDataSegment(dataSegment,
@@ -2185,11 +2238,12 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
     for (uint32_t iter = 0; iter < dataLimit; iter++)
     {
         result = CAMakeRemainDataSegment(dataSegment,
-                                         CA_BLE_NORMAL_SEGMENT_PAYLOAD_SIZE,
+                                         g_mtuSize - CA_BLE_HEADER_SIZE,
                                          data,
                                          dataLen,
                                          iter,
-                                         dataHeader);
+                                         dataHeader,
+                                         g_mtuSize);
 
         if (CA_STATUS_OK != result)
         {
@@ -2200,7 +2254,7 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
 
         result = CAUpdateCharacteristicsToAllGattClients(
                      dataSegment,
-                     CA_SUPPORTED_BLE_MTU_SIZE);
+                     g_mtuSize);
 
         if (CA_STATUS_OK != result)
         {
@@ -2211,7 +2265,7 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
         CALEDoEvents();
     }
 
-    if (remainingLen && (totalLength > CA_SUPPORTED_BLE_MTU_SIZE))
+    if (remainingLen && (totalLength > g_mtuSize))
     {
         // send the last segment of the data
         OIC_LOG(DEBUG, CALEADAPTER_TAG, "Sending the last chunk");
@@ -2221,7 +2275,8 @@ static CAResult_t CALEServerSendDataSingleThread(const uint8_t *data,
                                          data,
                                          dataLen,
                                          dataLimit,
-                                         dataHeader);
+                                         dataHeader,
+                                         g_mtuSize);
 
         if (CA_STATUS_OK != result)
         {
index 325e6ef..df00e46 100644 (file)
@@ -1191,4 +1191,25 @@ exit:
     return CA_STATUS_OK;
 }
 
+bool CALEClientIsConnected(const char* address)
+{
+    //@Todo
+    //it should be implemented after update Tizen 3.0
+    return true;
+}
+
+uint16_t CALEClientGetMtuSize(const char* address)
+{
+    VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
+    //@Todo
+    //it should be implemented after update Tizen 3.0
+    return CA_DEFAULT_BLE_MTU_SIZE;
+}
 
+CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize)
+{
+    VERIFY_NON_NULL(address, TAG, "address is null");
+    //@Todo
+    //it should be implemented after update Tizen 3.0
+    return CA_STATUS_OK;
+}
index c55e025..c808b95 100644 (file)
@@ -178,4 +178,28 @@ void CADiscoverLEServicesThread (void *remoteAddress);
  * @retval ::CA_STATUS_FAILED Operation failed.
  */
 CAResult_t CALEGattDiscoverServices(const char *remoteAddress);
+
+/**
+ * check connection status.
+ * @param[in] address      the address of the remote device.
+ * @return  true or false.
+ */
+bool CALEClientIsConnected(const char* address);
+
+/**
+ * get MTU size.
+ * @param[in] address      the address of the remote device.
+ * @return  mtu size negotiated from remote device.
+ */
+uint16_t CALEClientGetMtuSize(const char* address);
+
+/**
+ * This function is used to set MTU size
+ * which negotiated between client and server device.
+ * @param[in]   address       remote address.
+ * @param[in]   mtuSize       MTU size.
+ * @return  ::CA_STATUS_OK or ERROR CODES (::CAResult_t error codes in cacommon.h).
+ */
+CAResult_t CALEClientSetMtuSize(const char* address, uint16_t mtuSize);
+
 #endif /* TZ_BLE_CLIENT_H_ */
index 6e72ed5..af7a58e 100644 (file)
@@ -895,3 +895,28 @@ void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
 {
     g_serverErrorCallback = callback;
 }
+
+bool CALEServerIsConnected(const char* address)
+{
+    //@Todo
+    return true;
+}
+
+uint16_t CALEServerGetMtuSize(const char* address)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+    VERIFY_NON_NULL_RET(address, TAG, "address is null", CA_DEFAULT_BLE_MTU_SIZE);
+
+    unsigned int mtu = CA_DEFAULT_BLE_MTU_SIZE + CA_BLE_MTU_HEADER_SIZE;
+    int ret = bt_device_get_att_mtu(address, &mtu);
+    if (0 != ret)
+    {
+        OIC_LOG_V(ERROR, TAG,
+                  "bt_device_get_att_mtu failed with return [%s]", CALEGetErrorMsg(ret));
+        return CA_DEFAULT_BLE_MTU_SIZE;
+    }
+    OIC_LOG_V(INFO, TAG, "mtu size(including header) from bt_device_get_att_mtu is %d", mtu);
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return mtu - CA_BLE_MTU_HEADER_SIZE;
+}
+
index 400f81f..d84c4e9 100644 (file)
@@ -155,5 +155,19 @@ void CALEGattRemoteCharacteristicWriteCb(char *remoteAddress, bt_gatt_server_h s
  */
 void CASetLEConnectionStateChangedCallback(CALEConnectionStateChangedCallback connStateCb);
 
+/**
+ * check connection status.
+ * @param[in] address      the address of the remote device.
+ * @return  true or false.
+ */
+bool CALEServerIsConnected(const char* address);
+
+/**
+ * get MTU size.
+ * @param[in] address      the address of the remote device.
+ * @return  mtu size negotiated from remote device.
+ */
+uint16_t CALEServerGetMtuSize(const char* address);
+
 #endif /* TZ_BLE_SERVER_H_ */
 
index 8b760c1..791108e 100755 (executable)
 #include "oic_string.h"
 #include "oic_malloc.h"
 #include "cafragmentation.h"
+#include "caleinterface.h"
 
 #define CA_TRANSPORT_ADAPTER_SCOPE  1000
+#define CA_BLE_FIRST_SEGMENT_PAYLOAD_SIZE (((CA_DEFAULT_BLE_MTU_SIZE) - (CA_BLE_HEADER_SIZE)) \
+                                           - (CA_BLE_LENGTH_HEADER_SIZE))
+
 
 class CATests : public testing::Test {
     protected:
@@ -560,7 +564,8 @@ TEST(CAfragmentationTest, FragmentTest)
     EXPECT_EQ(CA_STATUS_OK, CAGenerateVariableForFragmentation(dataLen,
                                                                &midPacketCount,
                                                                &remainingLen,
-                                                               &totalLength));
+                                                               &totalLength,
+                                                               CA_DEFAULT_BLE_MTU_SIZE));
 
     uint8_t dataHeader[CA_BLE_HEADER_SIZE] = {0};
     const uint8_t tmpSourcePort = 1;
@@ -601,7 +606,8 @@ TEST(CAfragmentationTest, FragmentTest)
                                                     data,
                                                     dataLen,
                                                     0,
-                                                    dataHeader));
+                                                    dataHeader,
+                                                    CA_DEFAULT_BLE_MTU_SIZE));
     EXPECT_TRUE(dataSegment != NULL);
 
     free(data);
@@ -622,7 +628,8 @@ TEST(CAfragmentationTest, DefragmentTest)
     EXPECT_EQ(CA_STATUS_OK, CAGenerateVariableForFragmentation(dataLen,
                                                                &midPacketCount,
                                                                &remainingLen,
-                                                               &totalLength));
+                                                               &totalLength,
+                                                               CA_SUPPORTED_BLE_MTU_SIZE));
 
     uint8_t dataHeader[CA_BLE_HEADER_SIZE] = {0};
     const uint8_t tmpSourcePort = 1;