perf(machine): fewer NFC APDUs (E104-first) + single-attempt read
Retrying a read hammered the cheap CCID reader into a stuck present↔empty loop (only cleared by a reboot), so drop the retry: a read is a single attempt and the user re-taps if the RF link drops mid-read. Also skip the Capability-Container round-trip in the common case — NTAG424 Bolt Cards use NDEF FileID E104, so try E104/0004 directly and only read the CC to discover the id if both fail. Fewer APDUs → a read completes inside a shorter stable window. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ea736dfab0
commit
ed04c63b2f
1 changed files with 21 additions and 14 deletions
|
|
@ -87,21 +87,21 @@ export async function readNdefLnurlw(
|
|||
return null
|
||||
}
|
||||
|
||||
// Prefer the FileID advertised by the Capability Container (EF E103).
|
||||
const candidates: Array<[number, number]> = []
|
||||
// NTAG424 Bolt Cards use NDEF FileID E104. Try it (and 0004) directly to
|
||||
// minimise APDU round-trips over a flaky RF link; only fall back to reading
|
||||
// the Capability Container to discover the id if both direct reads fail.
|
||||
for (const fid of [[0xe1, 0x04] as [number, number], [0x00, 0x04] as [number, number]]) {
|
||||
const found = await readNdefFile(send, fid)
|
||||
if (found) return found
|
||||
}
|
||||
if (swOk(await send([0x00, 0xa4, 0x00, 0x0c, 0x02, 0xe1, 0x03]))) {
|
||||
const cc = await send([0x00, 0xb0, 0x00, 0x00, 0x0f])
|
||||
// CC layout: …[07]=TLV tag 0x04, [08]=len, [09..10]=NDEF FileID.
|
||||
if (swOk(cc) && cc.length >= 13 && cc[7] === 0x04) candidates.push([cc[9], cc[10]])
|
||||
}
|
||||
for (const fid of [[0xe1, 0x04] as [number, number], [0x00, 0x04] as [number, number]]) {
|
||||
if (!candidates.some((c) => c[0] === fid[0] && c[1] === fid[1])) candidates.push(fid)
|
||||
}
|
||||
|
||||
for (const fid of candidates) {
|
||||
const found = await readNdefFile(send, fid)
|
||||
if (swOk(cc) && cc.length >= 13 && cc[7] === 0x04) {
|
||||
const found = await readNdefFile(send, [cc[9], cc[10]])
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
@ -157,12 +157,19 @@ export async function startNfcReader(
|
|||
|
||||
r.on('card', async () => {
|
||||
onStatus({ state: 'reading', reader: name })
|
||||
// Single attempt: hammering a flaky RF link with retries wedges these
|
||||
// cheap CCID readers. A read is a few APDU round-trips; if the card
|
||||
// shifts mid-read the transmit fails and the user simply re-taps.
|
||||
try {
|
||||
const lnurlw = await readNdefLnurlw((apdu, maxLen) => r.transmit(apdu, maxLen))
|
||||
if (lnurlw) onCard(lnurlw)
|
||||
else onStatus({ state: 'error', reader: name, message: 'not a Bolt Card' })
|
||||
if (lnurlw) {
|
||||
onCard(lnurlw)
|
||||
} else {
|
||||
onStatus({ state: 'error', reader: name, message: 'not a Bolt Card' })
|
||||
}
|
||||
} catch (e) {
|
||||
onStatus({ state: 'error', reader: name, message: errMsg(e) })
|
||||
onStatus({ state: 'error', reader: name, message: 'card read failed — hold steady & retap' })
|
||||
void e
|
||||
}
|
||||
})
|
||||
r.on('card.off', () => onStatus({ state: 'card-removed', reader: name }))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue