Issue #51 fixed: restarting legacy bootloader on Invalid State
This commit is contained in:
parent
113c312985
commit
d5f487ed56
|
@ -411,32 +411,12 @@ import no.nordicsemi.android.error.LegacyDfuError;
|
||||||
*/
|
*/
|
||||||
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + " Status = " + status + ")");
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + " Status = " + status + ")");
|
||||||
|
|
||||||
// If upload was not completed in the previous connection the INVALID_STATE status will be reported.
|
// If upload was not completed in the previous connection the INVALID_STATE status will be reported.
|
||||||
// Theoretically, the connection could be resumed from that point, but there is no guarantee, that the same firmware
|
// Theoretically, the connection could be resumed from that point, but there is no guarantee, that the same firmware
|
||||||
// is to be uploaded now. It's safer to reset the device and start DFU again.
|
// is to be uploaded now. It's safer to reset the device and start DFU again.
|
||||||
if (status == LegacyDfuError.INVALID_STATE) {
|
if (status == LegacyDfuError.INVALID_STATE) {
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "Last upload interrupted. Restarting device...");
|
resetAndRestart(gatt, intent);
|
||||||
// Send 'jump to bootloader command' (Start DFU)
|
|
||||||
mProgressInfo.setProgress(DfuBaseService.PROGRESS_DISCONNECTING);
|
|
||||||
logi("Sending Reset command (Op Code = 6)");
|
|
||||||
writeOpCode(mControlPointCharacteristic, OP_CODE_RESET);
|
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Reset request sent");
|
|
||||||
|
|
||||||
// The device will reset so we don't have to send Disconnect signal.
|
|
||||||
mService.waitUntilDisconnected();
|
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_INFO, "Disconnected by the remote device");
|
|
||||||
|
|
||||||
final BluetoothGattService gas = gatt.getService(GENERIC_ATTRIBUTE_SERVICE_UUID);
|
|
||||||
final boolean hasServiceChanged = gas != null && gas.getCharacteristic(SERVICE_CHANGED_UUID) != null;
|
|
||||||
mService.refreshDeviceCache(gatt, !hasServiceChanged);
|
|
||||||
|
|
||||||
// Close the device
|
|
||||||
mService.close(gatt);
|
|
||||||
|
|
||||||
logi("Restarting the service");
|
|
||||||
final Intent newIntent = new Intent();
|
|
||||||
newIntent.fillIn(intent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_PACKAGE);
|
|
||||||
restartService(newIntent, false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (status != DFU_STATUS_SUCCESS)
|
if (status != DFU_STATUS_SUCCESS)
|
||||||
|
@ -480,6 +460,14 @@ import no.nordicsemi.android.error.LegacyDfuError;
|
||||||
response = readNotificationResponse();
|
response = readNotificationResponse();
|
||||||
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + " Status = " + status + ")");
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + " Status = " + status + ")");
|
||||||
|
|
||||||
|
// If upload was not completed in the previous connection the INVALID_STATE status will be reported.
|
||||||
|
// Theoretically, the connection could be resumed from that point, but there is no guarantee, that the same firmware
|
||||||
|
// is to be uploaded now. It's safer to reset the device and start DFU again.
|
||||||
|
if (status == LegacyDfuError.INVALID_STATE) {
|
||||||
|
resetAndRestart(gatt, intent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (status != DFU_STATUS_SUCCESS)
|
if (status != DFU_STATUS_SUCCESS)
|
||||||
throw new RemoteDfuException("Starting DFU failed", status);
|
throw new RemoteDfuException("Starting DFU failed", status);
|
||||||
} else
|
} else
|
||||||
|
@ -512,6 +500,14 @@ import no.nordicsemi.android.error.LegacyDfuError;
|
||||||
response = readNotificationResponse();
|
response = readNotificationResponse();
|
||||||
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
status = getStatusCode(response, OP_CODE_START_DFU_KEY);
|
||||||
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + ", Status = " + status + ")");
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Response received (Op Code = " + response[1] + ", Status = " + status + ")");
|
||||||
|
|
||||||
|
// If upload was not completed in the previous connection the INVALID_STATE status will be reported.
|
||||||
|
// Theoretically, the connection could be resumed from that point, but there is no guarantee, that the same firmware
|
||||||
|
// is to be uploaded now. It's safer to reset the device and start DFU again.
|
||||||
|
if (status == LegacyDfuError.INVALID_STATE) {
|
||||||
|
resetAndRestart(gatt, intent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (status != DFU_STATUS_SUCCESS)
|
if (status != DFU_STATUS_SUCCESS)
|
||||||
throw new RemoteDfuException("Starting DFU failed", status);
|
throw new RemoteDfuException("Starting DFU failed", status);
|
||||||
} else
|
} else
|
||||||
|
@ -845,4 +841,37 @@ import no.nordicsemi.android.error.LegacyDfuError;
|
||||||
if (!mConnected)
|
if (!mConnected)
|
||||||
throw new DeviceDisconnectedException("Unable to write Image Sizes: device disconnected");
|
throw new DeviceDisconnectedException("Unable to write Image Sizes: device disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends Reset command to the target device to reset its state and restarts the DFU Service that will start again.
|
||||||
|
* @param gatt the GATT device
|
||||||
|
* @param intent intent used to start the service
|
||||||
|
* @throws DfuException
|
||||||
|
* @throws DeviceDisconnectedException
|
||||||
|
* @throws UploadAbortedException
|
||||||
|
*/
|
||||||
|
private void resetAndRestart(final BluetoothGatt gatt, final Intent intent) throws DfuException, DeviceDisconnectedException, UploadAbortedException {
|
||||||
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_WARNING, "Last upload interrupted. Restarting device...");
|
||||||
|
// Send 'jump to bootloader command' (Start DFU)
|
||||||
|
mProgressInfo.setProgress(DfuBaseService.PROGRESS_DISCONNECTING);
|
||||||
|
logi("Sending Reset command (Op Code = 6)");
|
||||||
|
writeOpCode(mControlPointCharacteristic, OP_CODE_RESET);
|
||||||
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_APPLICATION, "Reset request sent");
|
||||||
|
|
||||||
|
// The device will reset so we don't have to send Disconnect signal.
|
||||||
|
mService.waitUntilDisconnected();
|
||||||
|
mService.sendLogBroadcast(DfuBaseService.LOG_LEVEL_INFO, "Disconnected by the remote device");
|
||||||
|
|
||||||
|
final BluetoothGattService gas = gatt.getService(GENERIC_ATTRIBUTE_SERVICE_UUID);
|
||||||
|
final boolean hasServiceChanged = gas != null && gas.getCharacteristic(SERVICE_CHANGED_UUID) != null;
|
||||||
|
mService.refreshDeviceCache(gatt, !hasServiceChanged);
|
||||||
|
|
||||||
|
// Close the device
|
||||||
|
mService.close(gatt);
|
||||||
|
|
||||||
|
logi("Restarting the service");
|
||||||
|
final Intent newIntent = new Intent();
|
||||||
|
newIntent.fillIn(intent, Intent.FILL_IN_COMPONENT | Intent.FILL_IN_PACKAGE);
|
||||||
|
restartService(newIntent, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue