From 4469e173cd0ced397f9a7abc53af2cd86b66f174 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 2 Jan 2026 23:05:12 +0000 Subject: [PATCH] firmware/sagas: add check for new SPIKE Prime bootloader version --- src/firmware/alerts/UnsupportedDfuHub.tsx | 24 +++++++++++++++++++++++ src/firmware/alerts/index.ts | 4 +++- src/firmware/alerts/translations/en.json | 3 +++ src/firmware/sagas.ts | 11 ++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/firmware/alerts/UnsupportedDfuHub.tsx diff --git a/src/firmware/alerts/UnsupportedDfuHub.tsx b/src/firmware/alerts/UnsupportedDfuHub.tsx new file mode 100644 index 00000000..23e4a910 --- /dev/null +++ b/src/firmware/alerts/UnsupportedDfuHub.tsx @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2025-2026 The Pybricks Authors + +import { Intent } from '@blueprintjs/core'; +import { Error } from '@blueprintjs/icons'; +import React from 'react'; +import type { CreateToast } from '../../toasterTypes'; +import { useI18n } from './i18n'; + +const UnsupportedDfuHub: React.FunctionComponent = () => { + const i18n = useI18n(); + return ( + <> +

{i18n.translate('unsupportedDfuHub.message')}

+ + ); +}; + +export const unsupportedDfuHub: CreateToast = (onAction) => ({ + message: , + icon: , + intent: Intent.DANGER, + onDismiss: () => onAction('dismiss'), +}); diff --git a/src/firmware/alerts/index.ts b/src/firmware/alerts/index.ts index a6187418..1d922f91 100644 --- a/src/firmware/alerts/index.ts +++ b/src/firmware/alerts/index.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2022-2025 The Pybricks Authors +// Copyright (c) 2022-2026 The Pybricks Authors import { dfuError } from './DfuError'; import { flashProgress } from './FlashProgress'; @@ -8,6 +8,7 @@ import { noDfuInterface } from './NoDfuInterface'; import { noWebHid } from './NoWebHid'; import { noWebUsb } from './NoWebUsb'; import { releaseButton } from './ReleaseButton'; +import { unsupportedDfuHub } from './UnsupportedDfuHub'; export default { dfuError, @@ -17,4 +18,5 @@ export default { noWebHid, noWebUsb, releaseButton, + unsupportedDfuHub, }; diff --git a/src/firmware/alerts/translations/en.json b/src/firmware/alerts/translations/en.json index d43aa55d..d701b2b8 100644 --- a/src/firmware/alerts/translations/en.json +++ b/src/firmware/alerts/translations/en.json @@ -22,6 +22,9 @@ "installUsbDriverButton": "Install USB Driver", "configureUdevRulesButton": "Configure udev rules" }, + "unsupportedDfuHub": { + "message": "This hub has different internal electronics and requires a different firmware. Pybricks does not support this yet. We are working on it!" + }, "noDfuInterface": { "message": "This is very unusual. The USB device did not contain the expected interface." }, diff --git a/src/firmware/sagas.ts b/src/firmware/sagas.ts index 7ac4fea7..553166bf 100644 --- a/src/firmware/sagas.ts +++ b/src/firmware/sagas.ts @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2020-2025 The Pybricks Authors +// Copyright (c) 2020-2026 The Pybricks Authors import { FirmwareReader, @@ -754,6 +754,15 @@ function* handleFlashUsbDfu(action: ReturnType): Gen return; } + if ( + device.productId === LegoUsbProductId.SpikePrimeBootloader && + device.deviceVersionMajor !== 1 + ) { + yield* put(alertsShowAlert('firmware', 'unsupportedDfuHub')); + yield* put(firmwareDidFailToFlashUsbDfu()); + return; + } + const dfu = new WebDFU( device, // forceInterfacesName is needed to get the flash layout map