Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for Mifare application directory (resolves #2030) #2067

Merged
merged 2 commits into from
Apr 13, 2023

Conversation

jdbruner
Copy link
Contributor

@jdbruner jdbruner commented Apr 11, 2023

Add support for the Mifare Application Directory, as described in AN10787.

The application directory occupies sector 0 (blocks 1 and 2) and - for 2K and 4K cards - sector 16 (blocks 64, 65, and 66). The directory is actually a sector map that defines the assignment of sectors to applications. Applications are identified by a 16-bit value (encoded in little-endian order on two bytes).

Previously, MifareCard.FormatNdef created the application directory, assigning all sectors to NDEF content. The NDEF content could be read and written with TryReadNdefMessage and WriteNdefMessage. However, as noted in #2030, these methods assume that the entire card has been formatted for NDEF, so if the directory was formatted elsewhere and specifies something else, they do not work correctly. In addition, they do not handle the last eight sectors of a 4K card correctly (because those sectors are a different size than the first 32 sectors).

This contribution adds a new class MifareDirectory to manage the Mifare application directory for a MifareCard. The new class MifareDirectoryEntry describes a directory entry (i.e., the assignment of sectors to an application). The new class MifareApplicationIdentifier represents an application identifier.

MifareDirectory.CreateEmpty creates an empty MifareDirectory object for a specified MifareCard.

MifareDirectory.LoadFromCard loads the directory from a specified MifareCard.

GetApplications returns an enumeration of MifareDirectoryEntry objects representing the directory contents. TryGetApplication returns the MifareDirectoryEntry of a specified application, if it exists. Sectors are allocated to applications with Allocate and freed with Free. After the directory has been modified, it must be written back to the card with StoreToCard.

FormatNdef, IsFormattedNdef, WriteNdefMessage, and TryReadNdefMessage have been reimplemented to use the directory. An overload of FormatNdef can specify that only a portion of the card is to be allocated to NDEF content. The remainder is free and can be assigned to other applications. For example, to format 14 sectors for NDEF and assign one sector to an issuer-specific application ID, the following could be used:

        // MifareCard mifareCard was created previously
        var res = mifareCard.FormatNdef(14);
        if (res)
        {
            var cardIssuerId = new MifareApplicationIdentifier(0xFF01);
            var directory = MifareDirectory.LoadFromCard(mifareCard);
            var entry = directory?.Allocate(cardIssuerId, 1);
            res = entry is object;
            if (res)
            {
                directory!.CardPublisherSector = entry!.FirstSector;
                res = directory.StoreToCard(mifareCard.KeyB);
            }
        }

This was also added to the Pn532 sample code. In addition, some miscellaneous changes were made to both the Pn532 and Mfrc522 sample code (including a workaround for #1869).

Microsoft Reviewers: Open in CodeFlow

@ghost ghost added the area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio label Apr 11, 2023
Copy link
Member

@Ellerbach Ellerbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great improvement and much cleaner than originaly. Thanks for the improvement. Minor comments.


#endregion

private readonly ushort _appId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually place all the private variable first

return new MifareDirectoryEntry(appId, entry.FirstSector, numberOfSectors);
}

private readonly MifareCard _card;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, can you please move the private fields declaration on the top?

@joperezr joperezr added this to the v3.0.0 milestone Apr 13, 2023
@Ellerbach Ellerbach merged commit 46c95db into dotnet:main Apr 13, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Dec 8, 2023
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants