Skip to content

fix: replace blocking NFC calls with proper coroutine/suspend APIs across all platforms#238

Merged
codebutler merged 1 commit intomasterfrom
fix-nfc-readers
Feb 17, 2026
Merged

fix: replace blocking NFC calls with proper coroutine/suspend APIs across all platforms#238
codebutler merged 1 commit intomasterfrom
fix-nfc-readers

Conversation

@codebutler
Copy link
Owner

iOS:

  • Replace dispatch_semaphore bridging with suspendCancellableCoroutine in
    IosCardTransceiver, IosUltralightTechnology, IosVicinityTechnology, and
    IosFeliCaTagAdapter
  • Replace runBlocking in IosNfcScanner with CoroutineScope(Dispatchers.IO)
    • GCD semaphore to avoid blocking GCD's worker queue thread
  • Use DESFire native protocol directly instead of ISO 7816 SELECT, which
    requires AIDs registered in Info.plist (unregistered AIDs kill the session)
  • Add NFCPollingISO15693 to NFC session polling options for NFC-V support
  • Fix Xcode project paths from stale farebot-app/ to app/

Desktop:

  • Make NfcReaderBackend.scanLoop() a suspend function, removing runBlocking
    from PN53xReaderBackend and PcscReaderBackend
  • Wrap scan coroutine in try/finally to ensure _isScanning resets on cancel
  • Share a single libusb context in PN533Device instead of per-call init/exit

WebUSB:

  • Remove flush-on-open which left dangling transferIn promises that consumed
    subsequent device responses
  • Increase transferIn buffer from 64 to 265 bytes for full PN533 frames
  • Pass atrRetries to setMaxRetries so InListPassiveTarget self-resolves
    instead of relying on client-side abort (which WebUSB can't do)

DESFire:

  • Handle COMMAND_ABORTED (0xCA) status code as access control exception

…ross all platforms

iOS:
- Replace dispatch_semaphore bridging with suspendCancellableCoroutine in
  IosCardTransceiver, IosUltralightTechnology, IosVicinityTechnology, and
  IosFeliCaTagAdapter
- Replace runBlocking in IosNfcScanner with CoroutineScope(Dispatchers.IO)
  + GCD semaphore to avoid blocking GCD's worker queue thread
- Use DESFire native protocol directly instead of ISO 7816 SELECT, which
  requires AIDs registered in Info.plist (unregistered AIDs kill the session)
- Add NFCPollingISO15693 to NFC session polling options for NFC-V support
- Fix Xcode project paths from stale farebot-app/ to app/

Desktop:
- Make NfcReaderBackend.scanLoop() a suspend function, removing runBlocking
  from PN53xReaderBackend and PcscReaderBackend
- Wrap scan coroutine in try/finally to ensure _isScanning resets on cancel
- Share a single libusb context in PN533Device instead of per-call init/exit

WebUSB:
- Remove flush-on-open which left dangling transferIn promises that consumed
  subsequent device responses
- Increase transferIn buffer from 64 to 265 bytes for full PN533 frames
- Pass atrRetries to setMaxRetries so InListPassiveTarget self-resolves
  instead of relying on client-side abort (which WebUSB can't do)

DESFire:
- Handle COMMAND_ABORTED (0xCA) status code as access control exception
@codebutler codebutler merged commit 037f2fe into master Feb 17, 2026
6 checks passed
@codebutler codebutler deleted the fix-nfc-readers branch February 17, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments