diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index e206d70..c2bae49 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -1,5 +1,6 @@
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java
index 6cd2b63..161b0a8 100644
--- a/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java
+++ b/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java
@@ -66,6 +66,7 @@ import no.nordicsemi.android.dfu.internal.exception.DeviceDisconnectedException;
import no.nordicsemi.android.dfu.internal.exception.DfuException;
import no.nordicsemi.android.dfu.internal.exception.HexFileValidationException;
import no.nordicsemi.android.dfu.internal.exception.RemoteDfuException;
+import no.nordicsemi.android.dfu.internal.exception.SizeValidationException;
import no.nordicsemi.android.dfu.internal.exception.UnknownResponseException;
import no.nordicsemi.android.dfu.internal.exception.UploadAbortedException;
import no.nordicsemi.android.dfu.internal.scanner.BootloaderScannerFactory;
@@ -378,7 +379,7 @@ public abstract class DfuBaseService extends IntentService {
*/
public static final int ERROR_FILE_ERROR = ERROR_MASK | 0x02;
/**
- * Thrown then input file is not a valid HEX or ZIP file.
+ * Thrown when input file is not a valid HEX or ZIP file.
*/
public static final int ERROR_FILE_INVALID = ERROR_MASK | 0x03;
/**
@@ -386,7 +387,7 @@ public abstract class DfuBaseService extends IntentService {
*/
public static final int ERROR_FILE_IO_EXCEPTION = ERROR_MASK | 0x04;
/**
- * Error thrown then {@code gatt.discoverServices();} returns false.
+ * Error thrown when {@code gatt.discoverServices();} returns false.
*/
public static final int ERROR_SERVICE_DISCOVERY_NOT_STARTED = ERROR_MASK | 0x05;
/**
@@ -413,6 +414,10 @@ public abstract class DfuBaseService extends IntentService {
* DFU Bootloader version 0.6+ requires sending the Init packet. If such bootloader version is detected, but the init packet has not been set this error is thrown.
*/
public static final int ERROR_INIT_PACKET_REQUIRED = ERROR_MASK | 0x0B;
+ /**
+ * Thrown when the firmware file is not word-aligned. The firmware size must be dividable by 4 bytes.
+ */
+ public static final int ERROR_FILE_SIZE_INVALID = ERROR_MASK | 0x0C;
/**
* Flag set then the DFU target returned a DFU error. Look for DFU specification to get error codes.
*/
@@ -770,6 +775,8 @@ public abstract class DfuBaseService extends IntentService {
}
} else {
loge("Connection state change error: " + status + " newState: " + newState);
+ if (newState == BluetoothGatt.STATE_DISCONNECTED)
+ mConnectionState = STATE_DISCONNECTED;
mPaused = false;
mError = ERROR_CONNECTION_STATE_MASK | status;
}
@@ -1178,6 +1185,10 @@ public abstract class DfuBaseService extends IntentService {
mInputStream = is;
imageSizeInBytes = mImageSizeInBytes = is.available();
+
+ if ((imageSizeInBytes % 4) != 0)
+ throw new SizeValidationException("The new firmware is not word-aligned.");
+
// Update the file type bit field basing on the ZIP content
if (fileType == TYPE_AUTO && MIME_TYPE_ZIP.equals(mimeType)) {
final ArchiveInputStream zhis = (ArchiveInputStream) is;
@@ -1187,6 +1198,15 @@ public abstract class DfuBaseService extends IntentService {
// Set the Init packet stream in case of a ZIP file
if (MIME_TYPE_ZIP.equals(mimeType)) {
final ArchiveInputStream zhis = (ArchiveInputStream) is;
+
+ // Validate sizes
+ if ((fileType & TYPE_APPLICATION) > 0 && (zhis.applicationImageSize() % 4) != 0)
+ throw new SizeValidationException("Application firmware is not word-aligned.");
+ if ((fileType & TYPE_BOOTLOADER) > 0 && (zhis.bootloaderImageSize() % 4) != 0)
+ throw new SizeValidationException("Bootloader firmware is not word-aligned.");
+ if ((fileType & TYPE_SOFT_DEVICE) > 0 && (zhis.softDeviceImageSize() % 4) != 0)
+ throw new SizeValidationException("Soft Device firmware is not word-aligned.");
+
if (fileType == TYPE_APPLICATION) {
if (zhis.getApplicationInit() != null)
initIs = new ByteArrayInputStream(zhis.getApplicationInit());
@@ -1204,6 +1224,10 @@ public abstract class DfuBaseService extends IntentService {
loge("An exception occurred while opening file", e);
updateProgressNotification(ERROR_FILE_NOT_FOUND);
return;
+ } catch (final SizeValidationException e) {
+ loge("Firmware not word-aligned", e);
+ updateProgressNotification(ERROR_FILE_SIZE_INVALID);
+ return;
} catch (final IOException e) {
loge("An exception occurred while calculating file size", e);
updateProgressNotification(ERROR_FILE_ERROR);
@@ -2844,13 +2868,11 @@ public abstract class DfuBaseService extends IntentService {
}
private void loge(final String message) {
- if (BuildConfig.DEBUG)
- Log.e(TAG, message);
+ Log.e(TAG, message);
}
private void loge(final String message, final Throwable e) {
- if (BuildConfig.DEBUG)
- Log.e(TAG, message, e);
+ Log.e(TAG, message, e);
}
private void logw(final String message) {
diff --git a/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java b/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java
new file mode 100644
index 0000000..037e91f
--- /dev/null
+++ b/dfu/src/main/java/no/nordicsemi/android/dfu/internal/exception/SizeValidationException.java
@@ -0,0 +1,37 @@
+/*************************************************************************************************************************************************
+ * Copyright (c) 2015, Nordic Semiconductor
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ************************************************************************************************************************************************/
+
+package no.nordicsemi.android.dfu.internal.exception;
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown when the firmware size is not word-aligned (number of bytes does not divide by 4).
+ * This is the requirement for the DFU Bootloader.
+ */
+public class SizeValidationException extends IOException {
+ private static final long serialVersionUID = -6467104024030837875L;
+
+ public SizeValidationException(final String message) {
+ super(message);
+ }
+}
diff --git a/dfu/src/main/java/no/nordicsemi/android/error/GattError.java b/dfu/src/main/java/no/nordicsemi/android/error/GattError.java
index 5c7ed5a..defb40d 100644
--- a/dfu/src/main/java/no/nordicsemi/android/error/GattError.java
+++ b/dfu/src/main/java/no/nordicsemi/android/error/GattError.java
@@ -151,6 +151,8 @@ public class GattError {
return "DFU FILE ERROR";
case DfuBaseService.ERROR_FILE_INVALID:
return "DFU NOT A VALID HEX FILE";
+ case DfuBaseService.ERROR_FILE_SIZE_INVALID:
+ return "DFU FILE NOT WORD ALIGNED";
case DfuBaseService.ERROR_FILE_IO_EXCEPTION:
return "DFU IO EXCEPTION";
case DfuBaseService.ERROR_FILE_NOT_FOUND: