Some more changes

This commit is contained in:
Aleksander Nowakowski 2016-06-10 16:12:50 +02:00
parent 8b8932fd57
commit d4e24580d7
2 changed files with 86 additions and 57 deletions

View File

@ -451,15 +451,18 @@ import no.nordicsemi.android.error.SecureDfuError;
if (info.offset > 0) { if (info.offset > 0) {
try { try {
i = info.offset / info.maxSize; i = info.offset / info.maxSize;
final int bytesSentAndExecuted = info.maxSize * i; int bytesSentAndExecuted = info.maxSize * i;
final int bytesSentNotExecuted = info.offset - bytesSentAndExecuted; int bytesSentNotExecuted = info.offset - bytesSentAndExecuted;
// Read the same number of bytes from the current init packet to calculate local CRC32 // Read the same number of bytes from the current init packet to calculate local CRC32
if (bytesSentAndExecuted > 0) { if (bytesSentAndExecuted > 0) {
mFirmwareStream.read(new byte[bytesSentAndExecuted]); // Read executed bytes mFirmwareStream.read(new byte[bytesSentAndExecuted]); // Read executed bytes
mFirmwareStream.mark(info.maxSize); // Mark here mFirmwareStream.mark(info.maxSize); // Mark here
} }
mFirmwareStream.read(new byte[bytesSentNotExecuted]); // Read the rest if (bytesSentNotExecuted > 0) {
// This may be 0 if the whole last chunk was completed before. It may not have been executed and may have CRC error.
mFirmwareStream.read(new byte[bytesSentNotExecuted]); // Read the rest
}
// Calculate the CRC32 // Calculate the CRC32
final int crc = (int) (((ArchiveInputStream) mFirmwareStream).getCrc32() & 0xFFFFFFFFL); final int crc = (int) (((ArchiveInputStream) mFirmwareStream).getCrc32() & 0xFFFFFFFFL);
@ -469,10 +472,19 @@ import no.nordicsemi.android.error.SecureDfuError;
mProgressInfo.setBytesReceived(info.offset); mProgressInfo.setBytesReceived(info.offset);
resumeSendingData = true; resumeSendingData = true;
} else { } else {
if (bytesSentNotExecuted == 0) {
// Looks like the whole last chunk was invalid and not executed. We have to rewind last maxSize bytes as we don't have any mark there.
bytesSentAndExecuted -= info.maxSize;
bytesSentNotExecuted = info.maxSize;
((ArchiveInputStream) mFirmwareStream).rewind(info.maxSize);
mFirmwareStream.mark(info.maxSize);
}
// The CRC of the current object is not correct. If there was another Data object sent before, its CRC must have been correct, // The CRC of the current object is not correct. If there was another Data object sent before, its CRC must have been correct,
// as it has been executed. Either way, we have to create the current object again. // as it has been executed. Either way, we have to create the current object again.
mProgressInfo.setBytesSent(bytesSentAndExecuted); mProgressInfo.setBytesSent(bytesSentAndExecuted);
mProgressInfo.setBytesReceived(bytesSentAndExecuted); mProgressInfo.setBytesReceived(bytesSentAndExecuted);
info.offset -= bytesSentNotExecuted;
info.CRC32 = 0; // invalidate
mFirmwareStream.reset(); mFirmwareStream.reset();
} }
} catch (final IOException e) { } catch (final IOException e) {
@ -486,70 +498,74 @@ import no.nordicsemi.android.error.SecureDfuError;
} }
// Each page will be sent in MAX_ATTEMPTS // Each page will be sent in MAX_ATTEMPTS
int attempt = 1; if (info.offset < mImageSizeInBytes) {
while (mProgressInfo.getAvailableObjectSizeIsBytes() > 0) { int attempt = 1;
if (!resumeSendingData) { while (mProgressInfo.getAvailableObjectSizeIsBytes() > 0) {
// Create the Data object if (!resumeSendingData) {
logi("Creating Data object (Op Code = 1, Type = 2, Size = " + mProgressInfo.getAvailableObjectSizeIsBytes() + ") (" + (i + 1) + "/" + count + ")"); // Create the Data object
writeCreateRequest(OBJECT_DATA, mProgressInfo.getAvailableObjectSizeIsBytes()); logi("Creating Data object (Op Code = 1, Type = 2, Size = " + mProgressInfo.getAvailableObjectSizeIsBytes() + ") (" + (i + 1) + "/" + count + ")");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Data object (" + (i + 1) + "/" + count + ") created"); writeCreateRequest(OBJECT_DATA, mProgressInfo.getAvailableObjectSizeIsBytes());
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Data object (" + (i + 1) + "/" + count + ") created");
resumeSendingData = false; resumeSendingData = false;
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Uploading firmware..."); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Uploading firmware...");
} else { } else {
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Resuming uploading firmware..."); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Resuming uploading firmware...");
} }
// Send the current object part // Send the current object part
try { try {
logi("Uploading firmware..."); logi("Uploading firmware...");
uploadFirmwareImage(mPacketCharacteristic); uploadFirmwareImage(mPacketCharacteristic);
} catch (final DeviceDisconnectedException e) { } catch (final DeviceDisconnectedException e) {
loge("Disconnected while sending data"); loge("Disconnected while sending data");
throw e; throw e;
} }
// Calculate Checksum // Calculate Checksum
logi("Sending Calculate Checksum command (Op Code = 3)"); logi("Sending Calculate Checksum command (Op Code = 3)");
final ObjectChecksum checksum = readChecksum(); final ObjectChecksum checksum = readChecksum();
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, String.format(Locale.US, "Checksum received (Offset = %d, CRC = %08X)", checksum.offset, checksum.CRC32)); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, String.format(Locale.US, "Checksum received (Offset = %d, CRC = %08X)", checksum.offset, checksum.CRC32));
logi(String.format(Locale.US, "Checksum received (Offset = %d, CRC = %08X)", checksum.offset, checksum.CRC32)); logi(String.format(Locale.US, "Checksum received (Offset = %d, CRC = %08X)", checksum.offset, checksum.CRC32));
// Calculate the CRC32 // Calculate the CRC32
final int crc = (int) (((ArchiveInputStream) mFirmwareStream).getCrc32() & 0xFFFFFFFFL); final int crc = (int) (((ArchiveInputStream) mFirmwareStream).getCrc32() & 0xFFFFFFFFL);
if (crc == checksum.CRC32) { if (crc == checksum.CRC32) {
// Execute Init packet // Execute Init packet
logi("Executing data object (Op Code = 4)"); logi("Executing data object (Op Code = 4)");
writeExecute(); writeExecute();
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Data object executed"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Data object executed");
// Increment iterator // Increment iterator
i++; i++;
attempt = 1; attempt = 1;
} else { } else {
if (attempt < MAX_ATTEMPTS) { if (attempt < MAX_ATTEMPTS) {
attempt++; attempt++;
logi("CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); logi("CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")"); mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "CRC32 does not match! Retrying...(" + attempt + "/" + MAX_ATTEMPTS + ")");
try { try {
mFirmwareStream.reset(); mFirmwareStream.reset();
mProgressInfo.setBytesSent(checksum.offset - info.maxSize); mProgressInfo.setBytesSent(checksum.offset - info.maxSize);
} catch (final IOException e) { } catch (final IOException e) {
loge("Error while resetting the firmware stream", e); loge("Error while resetting the firmware stream", e);
mService.terminateConnection(gatt, DfuBaseService.ERROR_FILE_IO_EXCEPTION); mService.terminateConnection(gatt, DfuBaseService.ERROR_FILE_IO_EXCEPTION);
return;
}
} else {
loge("CRC32 does not match!");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC32 does not match!");
mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR);
return; return;
} }
} else {
loge("CRC32 does not match!");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_ERROR, "CRC32 does not match!");
mService.terminateConnection(gatt, DfuBaseService.ERROR_CRC_ERROR);
return;
} }
} }
final long endTime = SystemClock.elapsedRealtime();
logi("Transfer of " + mProgressInfo.getBytesSent() + " bytes has taken " + (endTime - startTime) + " ms");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Upload completed in " + (endTime - startTime) + " ms");
} else {
// Looks as if the whole file was sent correctly but
} }
final long endTime = SystemClock.elapsedRealtime();
logi("Transfer of " + mProgressInfo.getBytesSent() + " bytes has taken " + (endTime - startTime) + " ms");
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Upload completed in " + (endTime - startTime) + " ms");
} }
/** /**

View File

@ -350,6 +350,19 @@ public class ArchiveInputStream extends ZipInputStream {
bytesReadFromMarkedSource = bytesReadFromCurrentSource; bytesReadFromMarkedSource = bytesReadFromCurrentSource;
} }
public void rewind(final int offset) {
if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null))
throw new UnsupportedOperationException("Application must be sent in a separate connection.");
bytesRead = Math.max(bytesRead - offset, 0);
if (currentSource == bootloaderBytes && softDeviceBytes != null && bytesReadFromCurrentSource - offset < 0) {
currentSource = softDeviceBytes;
bytesReadFromCurrentSource = Math.max(softDeviceSize - (offset - bytesReadFromCurrentSource), 0);
} else {
bytesReadFromCurrentSource -= Math.max(bytesReadFromCurrentSource - offset, 0);
}
}
@Override @Override
public void reset() throws IOException { public void reset() throws IOException {
if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null)) if (applicationBytes != null && (softDeviceBytes != null || bootloaderBytes != null || softDeviceAndBootloaderBytes != null))