Skip to content
Merged
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ NSLayoutConstraint.activate([...])
### Empty States

List view controllers (Scanner, Dump, NDEF, Passport) use `EmptyStateView` for empty-list placeholders:

- Installed as a subview of the table view via `emptyState.install(on: tableView)`.
- Visibility toggled by checking the data store's `records.isEmpty`.
- Fades on scroll via `emptyState.updateAlpha(for: scrollView)` in `scrollViewDidScroll`.
Expand Down
4 changes: 2 additions & 2 deletions Example/CENFC/Configuration/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MARKETING_VERSION = 1.0.7
CURRENT_PROJECT_VERSION = 14
MARKETING_VERSION = 1.0.8
CURRENT_PROJECT_VERSION = 15
9 changes: 9 additions & 0 deletions Example/CENFC/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@
<string>90B7</string>
<string>927A</string>
<string>86A7</string>
<string>80DE</string>
<string>865E</string>
<string>8592</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
Expand All @@ -138,11 +141,17 @@
<string>A0000002472001</string>
<string>A000000167455349474E</string>
<string>A000000291</string>
<string>A000000404</string>
<string>A00000000386980701</string>
<string>A0000004520001</string>
<string>D4100000030001</string>
<string>D4100000140001</string>
<string>D410000029000001</string>
<string>D4100000300001</string>
<string>D4106509900020</string>
<string>A000000632010105</string>
<string>A000000341000101</string>
<string>5041592E535A54</string>
<string>D2760000850100</string>
<string>F049442E43484E</string>
<string>A000000812010208</string>
Expand Down
36 changes: 36 additions & 0 deletions Example/CENFCTests/NFCConfigurationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation
import Testing

struct NFCConfigurationTests {
@Test
func `ISO7816 select identifiers include implemented transit AIDs`() throws {
let identifiers = try #require(
Bundle.main.object(
forInfoDictionaryKey: "com.apple.developer.nfc.readersession.iso7816.select-identifiers"
) as? [String]
)

#expect(identifiers.contains("A000000632010105")) // China T-Union
#expect(identifiers.contains("A000000404")) // CardBal transit / stored-value app
#expect(identifiers.contains("5041592E535A54")) // Legacy Shenzhen Tong
#expect(identifiers.contains("A000000341000101")) // Singapore CEPAS discovery
#expect(identifiers.contains("D4100000030001")) // KSX6924 / Snapper-compatible discovery
#expect(identifiers.contains("D4100000300001")) // Snapper / MOIBA
#expect(identifiers.contains("D4106509900020")) // K-Cash
}

@Test
func `FeliCa system codes include CardBal transit codes`() throws {
let systemCodes = try #require(
Bundle.main.object(
forInfoDictionaryKey: "com.apple.developer.nfc.readersession.felica.systemcodes"
) as? [String]
)

#expect(systemCodes.contains("0003")) // Japan IC
#expect(systemCodes.contains("8008")) // Octopus
#expect(systemCodes.contains("80DE")) // CardBal transit code
#expect(systemCodes.contains("865E")) // CardBal transit code
#expect(systemCodes.contains("8592")) // CardBal transit code
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Foundation
/// ## References
/// - T-Union AID: A000000632010105
/// - Metrodroid ChinaTransitData / TUnionTransitData
/// - FareBot ChinaCard / TUnionTransitInfo
/// - NFSee: https://github.com/niceda/NFSee
///
/// ## Note
Expand All @@ -16,15 +17,29 @@ enum TUnionConstants {

// MARK: - File IDs

/// Main file containing balance, serial, and validity info.
/// Main file containing serial and validity info.
static let balanceFileID = Data([0x00, 0x15])
static let file15SFIReadP1: UInt8 = 0x95

/// T-Union transaction record SFI. CardBal documents this as a circular
/// 0x17-byte transaction/top-up record file.
static let transactionSFI: UInt8 = 0x18
static let transactionRecordLength: UInt8 = 0x17
static let maxTransactionRecords = 10

/// T-Union transit activity SFI. CardBal documents this as a circular
/// 0x30-byte travel activity record file.
static let transitActivitySFI: UInt8 = 0x1E
static let transitActivityRecordLength: UInt8 = 0x30
static let maxTransitActivityRecords = 30

// MARK: - GET BALANCE Command

/// Proprietary GET BALANCE: CLA=0x80 INS=0x5C P1=0x00 P2=0x02.
static let GET_BALANCE_CLA: UInt8 = 0x80
static let GET_BALANCE_INS: UInt8 = 0x5C
static let GET_BALANCE_P1: UInt8 = 0x00
static let GET_NEGATIVE_BALANCE_P1: UInt8 = 0x01
static let GET_BALANCE_P2: UInt8 = 0x02
static let GET_BALANCE_LE: UInt8 = 0x04

Expand All @@ -39,4 +54,15 @@ enum TUnionConstants {
/// Validity end: bytes 24-27 (4 bytes hex date YYYYMMDD).
static let validUntilOffset = 24
static let validUntilLength = 4

// MARK: - Transaction Record Layout

static let transactionAmountOffset = 5
static let transactionAmountLength = 4
static let transactionTypeOffset = 9
static let transactionStationOffset = 10
static let transactionStationLength = 6
static let transactionDateTimeOffset = 16
static let transactionDateTimeLength = 7
static let topUpType: UInt8 = 0x02
}
Loading