fix: make the examples report their failures, plus six correctness fixes - #10
Open
jeanpierrefortune wants to merge 8 commits into
Open
fix: make the examples report their failures, plus six correctness fixes#10jeanpierrefortune wants to merge 8 commits into
jeanpierrefortune wants to merge 8 commits into
Conversation
jeanpierrefortune
marked this pull request as draft
September 11, 2026 13:36
Two format strings passed one argument more than they had placeholders, so the logger threw from inside the error path, and the cause of an observation error was never printed.
Each main is now a runExample() called from a main that catches, logs the message and returns 1. An escaping exception used to reach abort() with exit code 3, no message, and the buffered log lost whenever output was redirected.
Thirteen files including the shared CalypsoConstants. The Service and PC/SC examples keep the previous AID because the cards available for those tests carry the old application, and the four stub files keep it because the simulated card IS that application.
The guard excluded only CARD_REMOVED, so UNAVAILABLE restarted a monitoring job on a reader being unregistered. This does NOT affect reader reconnection detection, which was a PC/SC plugin matter, and the executor now rejects such a post-shutdown job anyway; the guard keeps the log from showing a card removal sequence starting on a reader that just vanished.
UseCase3 activated the protocol under the name of the deprecated PcscSupportedContactlessProtocol, whose Innovatron constant carries a _CARD suffix, while the plugin keys its default rules from PcscCardCommunicationProtocol, without the suffix. The activation failed with "The card protocol INNOVATRON_B_PRIME_CARD is not supported". The new rule also matches more ATRs than the old one.
19 contactless ISO_14443_4 and 9 contact ISO_7816_3_T0 call sites moved to PcscCardCommunicationProtocol. Both moves are behaviour-neutral: the contactless name is the same string in both classes, and the three contact rules share the same ATR pattern. One call site keeps the deprecated class on purpose, UseCase2_ProtocolBasedSelection, because MIFARE_CLASSIC does not exist in the current one.
jeanpierrefortune
force-pushed
the
develop-2025-04-18-fix-win
branch
from
September 11, 2026 14:03
cb50bcf to
8f39fb9
Compare
UseCase6 and UseCase9 each declared their own copies of the PIN key references and PIN values, and those copies had drifted away from common/CalypsoConstants, which was until now used by nobody but its own translation unit. Both examples now take the four references from it. One of the four was wrong there: the verification ciphering key carried KVC 79h where the card under test expects 74h, the value both examples shipped. An encrypted Verify PIN answered 63C2, read as a wrong PIN, although the same PIN succeeded in plain form on the line above. With 74h in the shared file, UseCase6 runs its five steps and the attempt counter goes 3, 3, 2, 2, 3 as expected. The modification ciphering key keeps the 21h/79h of the shared file. Note that Change PIN still answers 6988, incorrect cryptogram, with that pair as well as with the 21h/74h the examples shipped, so neither value matches the key this card expects and the right one is still unknown. That is a separate question from the de-duplication done here.
findReader returns null when no reader name matches the regex, where the Java original throws. Every caller in the examples then called getName() on that null pointer, so a missing or renamed reader ended in an access violation with no diagnostic at all, the try/catch wrapper seeing no exception to report. Guard the seven call sites with an IllegalStateException naming the regex that matched nothing. The Calypso helper covers the twelve Calypso examples at once, for the card reader and the SAM reader alike. In UseCase4 the test also covers a reader found but not observable, since it applies to the result of the cast to ObservableCardReader.
jeanpierrefortune
force-pushed
the
develop-2025-04-18-fix-win
branch
from
September 11, 2026 15:06
8f39fb9 to
15c890d
Compare
|
jeanpierrefortune
marked this pull request as ready for review
September 11, 2026 15:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Eight changes to the examples, found while running the whole PC/SC suite on Windows with SpringCard Puck and Identive readers. Two of them are about error reporting and were a prerequisite to diagnosing everything else: before them, a failing example printed nothing at all.
The library fixes these examples exposed are in separate PRs on
keyple-card-calypso-cpp-lib,keyple-card-calypso-crypto-legacysam-cpp-lib,keyple-service-cpp-lib,keyple-plugin-pcsc-cpp-lib,keyple-util-cpp-libandkeypop-calypso-card-cpp-api.One commit per subject.
Error reporting
8d20977report the cause in the reader observer callbacks. Two format strings passed one argument more than they had placeholders, so the logger threw from inside the error path and the cause of an observation error was never printed.9119e5ecatch and report the exceptions escaping the examples. Eachmainbecomes arunExample()called from amainthat catches, logs the message and returns 1. An escaping exception used to reachabort()with exit code 3, no message, and the buffered log was lost whenever output was redirected.Correctness
58b2810do not finalize card processing on anUNAVAILABLEevent. The guard excluded onlyCARD_REMOVED, soUNAVAILABLErestarted a monitoring job on a reader being unregistered. The guard keeps the log from showing a card removal sequence starting on a reader that just vanished.dcadda4select the Innovatron protocol by the name the plugin registers.UseCase3_Rev1Selectionactivated the protocol under the name of the deprecatedPcscSupportedContactlessProtocol, whose Innovatron constant carries a_CARDsuffix. See the note below on how this interacts with the plugin.8e5f8e2take the PIN key references from the shared constants.UseCase6_VerifyPinandUseCase9_ChangePineach declared their own copies, which had drifted away fromcommon/CalypsoConstants. Details below.15c890dcheckfindReaderfor null before dereferencing the reader.findReaderreturns null when no reader name matches the regex, where the Java original throws. Every caller then calledgetName()on that null pointer, so a missing or renamed reader ended in an access violation with no diagnostic at all. The seven call sites now throw anIllegalStateExceptionnaming the regex that matched nothing.Housekeeping
40a83d5point the Calypso examples at the current test card AID. Thirteen files including the sharedCalypsoConstants. The Service and PC/SC examples keep the previous AID because the cards available for those tests carry the old application, and the four stub files keep it because the simulated card is that application.755260amigrate the examples off the deprecated PC/SC protocol classes. 19 contactless and 9 contact call sites move toPcscCardCommunicationProtocol. Both moves are behaviour-neutral: the contactless name is the same string in both classes, and the three contact rules share the same ATR pattern. One call site keeps the deprecated class on purpose,UseCase2_ProtocolBasedSelection, becauseMIFARE_CLASSICdoes not exist in the current one.This migration depends on the export fix in the
keyple-plugin-pcsc-cpp-libPR: without it,PcscCardCommunicationProtocoldoes not link on Windows.On the PIN key references
CalypsoConstantswas until now used by nobody but its own translation unit, which is how the two example copies drifted apart from it unnoticed. Both examples now take all four references, and the PIN values, from that one file.One of the four was wrong there. The verification ciphering key carried KVC 79h where the card under test expects 74h, the value both examples shipped. An encrypted Verify PIN answered 63C2, read as a wrong PIN, although the same PIN succeeded in plain form on the line above. With 74h in the shared file,
UseCase6_VerifyPinruns its five steps and the attempt counter goes 3, 3, 2, 2, 3 as expected.The modification ciphering key keeps the 21h/79h of the shared file. It is worth saying plainly that this pair does not work either:
UseCase9_ChangePinanswers 6988, incorrect cryptogram, with 21h/79h exactly as it does with the 21h/74h the examples shipped. So neither shipped value matches the key this card expects, and the right one is still unknown. The untried candidate is KIF 30h with KVC 74h, the key that works for verification. That question is separate from the de-duplication done here, and this PR does not claim to answer it.Note on the Innovatron commit
When this was found, the plugin keyed its default rules only from
PcscCardCommunicationProtocol, without the_CARDsuffix, so the example failed with "The card protocol INNOVATRON_B_PRIME_CARD is not supported". The PC/SC plugin has since started registering the deprecated names alongside the current ones, so the old name resolves again and the example is no longer broken by this.The commit is kept because it moves the example onto the non-deprecated name, consistently with the migration commit above. It is now a migration rather than a fix, and can be dropped if you prefer.
A format string this base corrects differently
This base changes the
%%of theUseCase12andUseCase13failure messages to%s.Logger::printftreats a bare%as the placeholder and%%as an escaped percent, so%sconsumes the argument and then prints a literals. The restructuring commit uses% %, three placeholders for three arguments, which is why it conflicts there. Worth a separate look on your side.Validation
The whole suite was run on hardware. Every example either completes or exits 1 with a message naming its cause, the one exception being
UseCase9_ChangePinand its open 6988 described above. The stub examples and the 761 unit tests of the dependency chain pass.