Skip to content

Commit d6e4807

Browse files
codebutlerclaude
andauthored
Add file 0xdf00 to KSX6924 file selectors (#213)
* Port CEPASProtocol from Metrodroid to fix APDU framing Fixes #191 The old FareBot CEPASProtocol manually built APDU commands but omitted the Le (expected response length) byte, causing cards to reject with 6D00 (instruction not supported). Replaced with Metrodroid's approach that delegates to ISO7816Protocol.sendRequest() for proper APDU framing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add file 0xdf00 to KSX6924 file selectors Metrodroid reads file 0xdf00 (decimal 57088) for T-Money cards in addition to files 1-5. This file may not exist on all KSX6924 cards, but ISO7816CardReader handles missing files gracefully. Ref: metrodroid/.../KSX6924Application.kt:199-204 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Apply ktlintFormat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add regression tests for KSX6924 file 0xdf00 support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fb38081 commit d6e4807

File tree

2 files changed

+87
-5
lines changed

2 files changed

+87
-5
lines changed

app/src/commonMain/kotlin/com/codebutler/farebot/shared/nfc/ISO7816Dispatcher.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,28 @@ object ISO7816Dispatcher {
108108
return selectors
109109
}
110110

111-
private fun buildKSX6924FileSelectors(): List<ISO7816CardReader.FileSelector> =
112-
(1..5).map { fileId ->
113-
ISO7816CardReader.FileSelector(
114-
parentDf = null,
115-
fileId = fileId,
111+
private fun buildKSX6924FileSelectors(): List<ISO7816CardReader.FileSelector> {
112+
val selectors = mutableListOf<ISO7816CardReader.FileSelector>()
113+
114+
// Files 1-5
115+
for (fileId in 1..5) {
116+
selectors.add(
117+
ISO7816CardReader.FileSelector(
118+
parentDf = null,
119+
fileId = fileId,
120+
),
116121
)
117122
}
123+
124+
// File 0xdf00 (T-Money cards)
125+
// This file may not exist on all cards, but ISO7816CardReader handles failures gracefully
126+
selectors.add(
127+
ISO7816CardReader.FileSelector(
128+
parentDf = null,
129+
fileId = 0xdf00,
130+
),
131+
)
132+
133+
return selectors
134+
}
118135
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* ISO7816DispatcherTest.kt
3+
*
4+
* This file is part of FareBot.
5+
* Learn more at: https://codebutler.github.io/farebot/
6+
*
7+
* Copyright (C) 2026 Eric Butler <eric@codebutler.com>
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
package com.codebutler.farebot.test
24+
25+
import com.codebutler.farebot.card.ksx6924.KSX6924Application
26+
import com.codebutler.farebot.shared.nfc.ISO7816Dispatcher
27+
import kotlin.test.Test
28+
import kotlin.test.assertEquals
29+
import kotlin.test.assertNotNull
30+
import kotlin.test.assertNull
31+
import kotlin.test.assertTrue
32+
33+
class ISO7816DispatcherTest {
34+
@Test
35+
fun testKSX6924FileSelectorsIncludesDf00() {
36+
val configs = ISO7816Dispatcher.buildAppConfigs()
37+
val ksx6924Config = configs.find { it.type == KSX6924Application.TYPE }
38+
assertNotNull(ksx6924Config, "KSX6924 config should be present")
39+
40+
val fileSelectors = ksx6924Config.fileSelectors
41+
val fileIds = fileSelectors.map { it.fileId }
42+
43+
// Files 1-5 should be present
44+
for (fileId in 1..5) {
45+
assertTrue(
46+
fileId in fileIds,
47+
"File selector for file $fileId should be present",
48+
)
49+
}
50+
51+
// File 0xdf00 should be present (T-Money cards)
52+
assertTrue(
53+
0xdf00 in fileIds,
54+
"File selector for file 0xdf00 should be present",
55+
)
56+
57+
// Total should be 6 selectors
58+
assertEquals(6, fileSelectors.size, "Should have exactly 6 file selectors")
59+
60+
// All KSX6924 file selectors should have null parentDf
61+
for (selector in fileSelectors) {
62+
assertNull(selector.parentDf, "KSX6924 file selectors should have null parentDf")
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)