diff --git a/src/screens/ResultScreen.tsx b/src/screens/ResultScreen.tsx index 44d4c3f..aaa83a5 100644 --- a/src/screens/ResultScreen.tsx +++ b/src/screens/ResultScreen.tsx @@ -219,102 +219,102 @@ export function ResultScreen({ route, navigation }: ResultScreenProps) { {transponder && (chipInfo || chipFamilyInfo) && ( - setShowChipInfo(!showChipInfo)} - style={styles.chipInfoHeader} - activeOpacity={0.7}> - - ABOUT THIS CHIP - - - {showChipInfo ? '▼' : '▶'} - - + setShowChipInfo(!showChipInfo)} + style={styles.chipInfoHeader} + activeOpacity={0.7}> + + ABOUT THIS CHIP + + + {showChipInfo ? '▼' : '▶'} + + - {showChipInfo && ( - <> - + {showChipInfo && ( + <> + - {/* Family description */} - {chipFamilyInfo && ( - - {chipFamilyInfo} - - )} - - {/* Detailed chip info */} - {chipInfo && ( - <> - - {chipInfo.description} + {/* Family description */} + {chipFamilyInfo && ( + + {chipFamilyInfo} + )} + + {/* Detailed chip info */} + {chipInfo && ( + <> + + {chipInfo.description} + + + {chipInfo.memoryNote && ( + + + Memory: + + + {chipInfo.memoryNote} + + + )} - {chipInfo.memoryNote && ( - Memory: + Security: - - {chipInfo.memoryNote} + + {chipInfo.securityLevel.toUpperCase()} - )} - - - Security: + + {getSecurityLevelDescription(chipInfo.securityLevel)} - - {chipInfo.securityLevel.toUpperCase()} - - - - {getSecurityLevelDescription(chipInfo.securityLevel)} - - - {chipInfo.commonUses.length > 0 && ( - <> - - COMMON USES - - {chipInfo.commonUses.map((use, idx) => ( - - • {use} + {chipInfo.commonUses.length > 0 && ( + <> + + COMMON USES - ))} - - )} + {chipInfo.commonUses.map((use, idx) => ( + + • {use} + + ))} + + )} - {chipInfo.capabilities.length > 0 && ( - <> - - CAPABILITIES - - {chipInfo.capabilities.map((cap, idx) => ( - - • {cap} + {chipInfo.capabilities.length > 0 && ( + <> + + CAPABILITIES - ))} - - )} - - )} - - )} - + {chipInfo.capabilities.map((cap, idx) => ( + + • {cap} + + ))} + + )} + + )} + + )} + )} @@ -341,6 +341,9 @@ export function ResultScreen({ route, navigation }: ResultScreenProps) { textStyle={styles.formFactorChipText}> {product.formFactor.replace('_', ' ')} + {product.formFactor.startsWith("X") && Injectable} + {product.formFactor.startsWith("B") && Large, rigid} + {product.formFactor.startsWith("F") && Large, semi-rigid} @@ -390,28 +393,28 @@ export function ResultScreen({ route, navigation }: ResultScreenProps) { {transponder && matchResult && matchResult.exactMatches.length === 0 && matchResult.cloneTargets.length === 0 && ( - - NO DIRECT MATCH - - + + NO DIRECT MATCH + + - - {getMatchSummary(matchResult, transponder.chipName)} - + + {getMatchSummary(matchResult, transponder.chipName)} + - {matchResult.familyMatches.length > 0 && ( - <> - - Related products in the same chip family: - - {matchResult.familyMatches.slice(0, 2).map(product => ( - - • {product.name} + {matchResult.familyMatches.length > 0 && ( + <> + + Related products in the same chip family: - ))} - - )} - + {matchResult.familyMatches.slice(0, 2).map(product => ( + + • {product.name} + + ))} + + )} + )} @@ -419,29 +422,29 @@ export function ResultScreen({ route, navigation }: ResultScreenProps) { {transponder?.sakSwapInfo?.hasSakSwap && ( - - SAK SWAP DETECTED - - + + SAK SWAP DETECTED + + - - {transponder.sakSwapInfo.swapType?.replace(/_/g, ' ').toUpperCase()} - + + {transponder.sakSwapInfo.swapType?.replace(/_/g, ' ').toUpperCase()} + - - {transponder.sakSwapInfo.description} - + + {transponder.sakSwapInfo.description} + - {transponder.sakSwapInfo.notes && transponder.sakSwapInfo.notes.length > 0 && ( - - {transponder.sakSwapInfo.notes.map((note, index) => ( - - • {note} - - ))} - - )} - + {transponder.sakSwapInfo.notes && transponder.sakSwapInfo.notes.length > 0 && ( + + {transponder.sakSwapInfo.notes.map((note, index) => ( + + • {note} + + ))} + + )} + )} @@ -449,90 +452,90 @@ export function ResultScreen({ route, navigation }: ResultScreenProps) { - {tagData ? ( - <> - - - UID - - - {tagData.uid || 'N/A'} - - - - - - TECHNOLOGIES - - { - tagData.techTypes.map((t, i) => - - {t} - ) - } - - - {tagData.sak !== undefined && ( + {tagData ? ( + <> - - SAK + + UID - - 0x{tagData.sak.toString(16).toUpperCase().padStart(2, '0')} + + {tagData.uid || 'N/A'} - )} - {tagData.atqa && ( - - ATQA - - - {tagData.atqa} + + TECHNOLOGIES + { + tagData.techTypes.map((t, i) => + + {t} + ) + } - )} - {tagData.historicalBytes && ( - - - HISTORICAL BYTES - - - {tagData.historicalBytes} - - - )} - - ) : ( - - No tag data available - - )} - + {tagData.sak !== undefined && ( + + + SAK + + + 0x{tagData.sak.toString(16).toUpperCase().padStart(2, '0')} + + + )} + + {tagData.atqa && ( + + + ATQA + + + {tagData.atqa} + + + )} + + {tagData.historicalBytes && ( + + + HISTORICAL BYTES + + + {tagData.historicalBytes} + + + )} + + ) : ( + + No tag data available + + )} + {/* No Detection Card (fallback) */} {!transponder && ( - - CHIP NOT IDENTIFIED - - - - Unable to identify this chip type. It may be unsupported or require advanced detection. - - - Need help? Ask on our forum for assistance. - - Linking.openURL(buildTrackedUrl('https://dngr.us/forum', 'unknown_chip'))} - > - VISIT FORUM - - + + CHIP NOT IDENTIFIED + + + + Unable to identify this chip type. It may be unsupported or require advanced detection. + + + Need help? Ask on our forum for assistance. + + Linking.openURL(buildTrackedUrl('https://dngr.us/forum', 'unknown_chip'))} + > + VISIT FORUM + + )} diff --git a/src/services/detection/desfire.ts b/src/services/detection/desfire.ts index 1105200..eb20b38 100644 --- a/src/services/detection/desfire.ts +++ b/src/services/detection/desfire.ts @@ -78,13 +78,27 @@ export function detectSpark2FromNdef( /** * Product type values from GET_VERSION byte 1 + * Per NXP datasheets: + * - NTAG 413 DNA (NT4H1321): Type 0x04, Subtype 0x02 + * - NTAG 424 DNA (NT4H2421): Type 0x04, Subtype 0x05 + * - NTAG 424 DNA TT: Type 0x04, Subtype 0x04 + * - DESFire EV1/EV2/EV3: Type 0x01 */ const PRODUCT_TYPES = { DESFIRE: 0x01, // Standard DESFire - NTAG: 0x04, // NTAG family (including NTAG 413 DNA which uses 0x04) + NTAG_DNA: 0x04, // NTAG DNA family (413/424) - distinguished by subtype NTAG_I2C: 0x05, // NTAG I2C family (can have ISO-DEP on Plus variants) DESFIRE_LIGHT: 0x08, // DESFire Light - NTAG_424_DNA: 0x21, // NTAG 424 DNA family +} as const; + +/** + * NTAG DNA subtype values from GET_VERSION byte 2 + * Per NXP NT4H1321 and NT4H2421 datasheets + */ +const NTAG_DNA_SUBTYPES = { + NTAG413_DNA: 0x02, // NTAG 413 DNA + NTAG424_DNA_TT: 0x04, // NTAG 424 DNA TagTamper + NTAG424_DNA: 0x05, // NTAG 424 DNA } as const; /** @@ -246,29 +260,31 @@ export async function detectDesfire(): Promise { // Determine chip type based on product type and version let chipType: ChipType; - if (hwProductType === PRODUCT_TYPES.NTAG_424_DNA) { - // NTAG 424 DNA family uses product type 0x21 - // Subtype 0x02 = TagTamper variant (424 DNA TT only) - // Storage size helps differentiate: - // - NTAG 413 DNA: ~160 bytes user memory (storage code <= 0x0E) - // - NTAG 424 DNA: ~416 bytes user memory (storage code >= 0x0F) - if (hwSubtype === 0x02) { - chipType = ChipType.NTAG424_DNA_TT; - } else if (hwStorageSize <= 0x0e) { - // Smaller storage indicates NTAG 413 DNA (~160 bytes) - chipType = ChipType.NTAG413_DNA; - } else { - // Larger storage indicates NTAG 424 DNA (~416 bytes) - chipType = ChipType.NTAG424_DNA; + if (hwProductType === PRODUCT_TYPES.NTAG_DNA) { + // NTAG DNA family (413/424) - distinguish by subtype per NXP datasheets + // NT4H1321 (NTAG 413 DNA): Subtype 0x02, Major 0x04 + // NT4H2421 (NTAG 424 DNA): Subtype 0x05, Major 0x04 + // NT4H2421 TT (NTAG 424 DNA TagTamper): Subtype 0x04, Major 0x04 + switch (hwSubtype) { + case NTAG_DNA_SUBTYPES.NTAG413_DNA: + console.log('[DESFire] Detected NTAG 413 DNA (product 0x04, subtype 0x02)'); + chipType = ChipType.NTAG413_DNA; + break; + case NTAG_DNA_SUBTYPES.NTAG424_DNA_TT: + console.log('[DESFire] Detected NTAG 424 DNA TT (product 0x04, subtype 0x04)'); + chipType = ChipType.NTAG424_DNA_TT; + break; + case NTAG_DNA_SUBTYPES.NTAG424_DNA: + console.log('[DESFire] Detected NTAG 424 DNA (product 0x04, subtype 0x05)'); + chipType = ChipType.NTAG424_DNA; + break; + default: + // Unknown NTAG DNA subtype - log and fall back to 424 DNA as most common + console.warn( + `[DESFire] Unknown NTAG DNA subtype: 0x${hwSubtype.toString(16)}, major: 0x${hwMajor.toString(16)}`, + ); + chipType = ChipType.NTAG424_DNA; } - } else if (hwProductType === PRODUCT_TYPES.NTAG && hwMajor >= 0x30) { - // NTAG 413 DNA returns product type 0x04 (like regular NTAG) but with: - // - hwMajor >= 0x30 (typically 0x30) - // - hwStorageSize 0x11 (different meaning than regular NTAG) - // - Responds to IsoDep (unlike regular NTAG 21x) - // Per NXP NT4H1321 datasheet, NTAG 413 DNA uses this response format - console.log('[DESFire] Detected NTAG 413 DNA (product type 0x04, hwMajor 0x30+)'); - chipType = ChipType.NTAG413_DNA; } else if (hwProductType === PRODUCT_TYPES.NTAG_I2C) { // NTAG I2C family (can have ISO-DEP on Plus variants) // Per NXP NT3H2111/NT3H2211 datasheet: