feat: switch firmware updates to bootloader OTA

This commit is contained in:
2026-04-29 18:02:48 +02:00
parent b673c9100d
commit 06834a0cc0
7 changed files with 781 additions and 1097 deletions

View File

@ -18,8 +18,6 @@ const String universalShifterDfuControlCharacteristicUuid =
'0993826f-0ee4-4b37-9614-d13ecba40008';
const String universalShifterDfuDataCharacteristicUuid =
'0993826f-0ee4-4b37-9614-d13ecba40009';
const String universalShifterDfuAckCharacteristicUuid =
'0993826f-0ee4-4b37-9614-d13ecba4000a';
const String universalShifterDfuStatusCharacteristicUuid =
'0993826f-0ee4-4b37-9614-d13ecba4000a';
const String ftmsServiceUuid = '00001826-0000-1000-8000-00805f9b34fb';
@ -41,15 +39,12 @@ const int universalShifterDfuOpcodeAbort = 0x03;
const int universalShifterDfuOpcodeGetStatus = 0x04;
const int universalShifterDfuFrameSizeBytes = 64;
const int universalShifterDfuFramePayloadSizeBytes = 63;
const int universalShifterBootloaderDfuDataHeaderSizeBytes = 9;
const int universalShifterBootloaderDfuMaxPayloadSizeBytes =
universalShifterDfuFrameSizeBytes -
universalShifterBootloaderDfuDataHeaderSizeBytes;
const int universalShifterBootloaderDfuStatusSizeBytes = 6;
const int universalShifterAttWriteOverheadBytes = 3;
const int universalShifterDfuMinimumMtu =
universalShifterDfuFrameSizeBytes + universalShifterAttWriteOverheadBytes;
const int universalShifterDfuPreferredMtu = 128;
const int universalShifterDfuAppStart = 0x00030000;
@ -78,9 +73,14 @@ const int trainerScanDeviceFlagConnectable = 0x08;
enum DfuUpdateState {
idle,
starting,
waitingForAck,
enteringBootloader,
connectingBootloader,
waitingForStatus,
erasing,
transferring,
finishing,
rebooting,
verifying,
completed,
aborted,
failed,
@ -119,18 +119,20 @@ class DfuUpdateProgress {
required this.state,
required this.totalBytes,
required this.sentBytes,
required this.lastAckedSequence,
required this.expectedOffset,
required this.sessionId,
required this.flags,
this.bootloaderStatus,
this.errorMessage,
});
final DfuUpdateState state;
final int totalBytes;
final int sentBytes;
final int lastAckedSequence;
final int expectedOffset;
final int sessionId;
final DfuUpdateFlags flags;
final DfuBootloaderStatus? bootloaderStatus;
final String? errorMessage;
double get fractionComplete {
@ -191,61 +193,6 @@ class DfuBootloaderStatus {
bool get isOk => code == DfuBootloaderStatusCode.ok;
}
enum DfuPreflightFailureReason {
deviceNotConnected,
wrongConnectedDevice,
mtuRequestFailed,
mtuTooLow,
}
class DfuPreflightResult {
const DfuPreflightResult._({
required this.requestedMtu,
required this.requiredMtu,
required this.negotiatedMtu,
required this.failureReason,
required this.message,
});
final int requestedMtu;
final int requiredMtu;
final int? negotiatedMtu;
final DfuPreflightFailureReason? failureReason;
final String? message;
bool get canStart => failureReason == null;
static DfuPreflightResult ready({
required int requestedMtu,
required int negotiatedMtu,
int requiredMtu = universalShifterDfuMinimumMtu,
}) {
return DfuPreflightResult._(
requestedMtu: requestedMtu,
requiredMtu: requiredMtu,
negotiatedMtu: negotiatedMtu,
failureReason: null,
message: null,
);
}
static DfuPreflightResult failed({
required int requestedMtu,
required DfuPreflightFailureReason failureReason,
required String message,
int requiredMtu = universalShifterDfuMinimumMtu,
int? negotiatedMtu,
}) {
return DfuPreflightResult._(
requestedMtu: requestedMtu,
requiredMtu: requiredMtu,
negotiatedMtu: negotiatedMtu,
failureReason: failureReason,
message: message,
);
}
}
class ShifterErrorInfo {
const ShifterErrorInfo({
required this.code,