Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,22 +305,34 @@ static NfcCommand mf_ultralight_poller_handler_get_feature_set(MfUltralightPolle
}

static NfcCommand mf_ultralight_poller_handler_read_signature(MfUltralightPoller* instance) {
MfUltralightPollerState next_state = MfUltralightPollerStateAuth;
bool signature_read_ok = false;

if(mf_ultralight_support_feature(
instance->feature_set, MfUltralightFeatureSupportReadSignature)) {
FURI_LOG_D(TAG, "Reading signature");
instance->error =
mf_ultralight_poller_read_signature(instance, &instance->data->signature);
if(instance->error != MfUltralightErrorNone) {
FURI_LOG_D(TAG, "Read signature failed");
next_state = MfUltralightPollerStateReadFailed;
if(instance->error == MfUltralightErrorNone) {
signature_read_ok = true;
} else {
FURI_LOG_D(TAG, "Read signature failed, continuing without signature");
memset(
instance->data->signature.data,
0,
sizeof(instance->data->signature.data));
}
} else {
FURI_LOG_D(TAG, "Skip reading signature");
if(mf_ultralight_support_feature(
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
next_state = MfUltralightPollerStateAuthMfulC;
}
}

MfUltralightPollerState next_state;
if(signature_read_ok) {
next_state = MfUltralightPollerStateAuth;
} else if(mf_ultralight_support_feature(
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
next_state = MfUltralightPollerStateAuthMfulC;
} else {
next_state = MfUltralightPollerStateAuth;
}
instance->state = next_state;

Expand Down
53 changes: 53 additions & 0 deletions test-with-nfc-hardware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
## 1. Build and flash this branch
On your machine (with the repo and this branch checked out):
```bash
cd /Users/jclaus/dev/flipperzero-firmware
git checkout ISSUE-4106/fix-nfc-mifare-ultralight-card # if not already
./fbt
Connect the Flipper over USB (powered on, normal firmware running), then:

./fbt flash_usb
Wait until the Flipper reboots. You're now running the fixed firmware.

2. Test with NFC app (normal read)
Open NFC — Main menu → NFC.
Start a read — Read (or Scan / Detect, depending on menu wording).
Hold the card — Put the Mifare Ultralight or NTAG213 flat on the back of the Flipper and keep it still.
Expected with the fix — After a short "Don't move" phase, you get a success (and optionally "Save"). No endless "Don't move" even if the card is one that used to get stuck (e.g. signature read failing).
If you have a card that used to get stuck on official/unfixed firmware, that's the main case to retest: it should now complete instead of hanging.

3. What to check
Behavior — Read finishes and shows success (and you can save the dump). No infinite "Don't move".
Saved dump — Open the saved file: UID, type (e.g. NTAG213), and page data should look correct. Signature may be all zeros if that read failed (that's expected with the fix).
Optional – debug log — If you use ./fbt debug or a serial/debug console and enable debug logs, you may see:
Read signature failed, continuing without signature when the fix path is used.
Then the read continues and completes instead of going to "Read Failed".
4. Optional: compare with unfixed firmware
To see the old bug and confirm the fix:

Flash stock/unfixed firmware (e.g. dev or latest release):

git stash
git checkout dev
./fbt flash_usb
Try the same card that used to get stuck: run NFC → Read, hold card. If it still reproduces, you'll see it hang on "Don't move".

Flash your branch again:

git checkout ISSUE-4106/fix-nfc-mifare-ultralight-card
git stash pop # if you stashed
./fbt flash_usb
Retest the same card — read should now complete.

5. Testing multiple devices/cards
Several Flippers — Repeat "build once → ./fbt flash_usb" for each device (plug one at a time, or use ./fbt flash_usb -p /dev/cu.usbmodem* to pick a port if needed).
Several cards — Use at least:
One Mifare Ultralight (or compatible).
One NTAG213 (or NTAG215/216).
If you have one that used to get stuck (e.g. ATQA 0x0044, SAK 0x00), that's the most important to test.
6. Quick checklist
Step Action
1 ./fbt then ./fbt flash_usb on branch ISSUE-4106/fix-nfc-mifare-ultralight-card
2 NFC → Read, hold Ultralight/NTAG213 until read finishes
3 Confirm success (no endless "Don't move"), save and open dump
4 (Optional) Flash dev, reproduce hang, then re-flash branch and confirm fix