Skip to content
Open
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
Binary file added .DS_Store
Binary file not shown.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,7 @@ cython_debug/

# Docs site
public/

# MacOS
.DS_Store
**/.DS_Store
31 changes: 29 additions & 2 deletions src/desfire/schemas/card_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,36 @@ def __init__(self, data: list[int]):

def __repr__(self) -> str:
temp = "--- Desfire Card Details ---\r\n"
temp += f"Hardware Version: {self.hardware_minor_version}.{self.hardware_minor_version}\r\n"
temp += f"Hardware Version: {self.hardware_major_version}.{self.hardware_minor_version}\r\n"
temp += f"Software Version: {self.software_major_version}.{self.software_minor_version}\r\n"
temp += f"EEPROM size: {1 << (self.hardware_storage_size - 1)} bytes\r\n"

# EEPROM size calculation according to NXP documentation,
# see https://www.nxp.com/docs/en/application-note/AN10833.pdf
# Formula is in Figure 1 on page 4, lower right corner of the table, but a bit unclear.
# . Examples are in the table itself below some card types, e.g. MIFARE DESFire
# see also https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf
# on page 36, Table 28 and notes below
#
# Meaning and encoding of 'hardware_storage_size':
# Bit 0 (LSB) indicates the size encoding method
# Bit 1..7 are the 'size' value used in the formula below
#
# Formula:
# if bit 0 = 1, then storageBytes = 2^(size // 2) up to storageBytes = 2^(size // 2 + 1)
# if bit 0 = 0, then storageBytes = 2^(size // 2)
#
# Examples:
# Ultralight Family, e.g. Ultralight C has bit 0 = 1, e.g. 0x0B (for 48 Byte) or 0x0E (128 Byte)
# MIFARE DESFire Family has bit 0 = 0, e.g. 0x16: 2K, 0x18: 4K, 0x1A: 8K, 0x1C: 16K, 0x1E: 32K
#
# LSB indicates size encoding method
if (self.hardware_storage_size & 0x01) == 0x01: # typical for Ultralight C, and EV1
temp += (
f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} up to "
f"{1 << ((self.hardware_storage_size >> 1) + 1)} bytes\r\n"
)
else: # typical for DESFire EV1, EV2, and EV3
temp += f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} bytes\r\n"
temp += f"Production: week {self.production_date_cw:X}, year 20{self.production_date_year:02X}\r\n"
temp += f"UID no: {to_hex_string(self.uid)}\r\n"
temp += f"Batch no: {to_hex_string(self.batch_no)}\r\n"
Expand Down
61 changes: 61 additions & 0 deletions tests/tests_test_card_version_repr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from desfire.schemas.card_version import CardVersion


def test_card_version_repr_hardware_major_minor():
# Prepare data for real MIFARE DESFire EV1 card with 4K from 2013
data = [
0x04, # first block, hardware vendor id
0x01,
0x01,
0x01,
0x00,
0x18,
0x05,
0x04, # second block, software vendor id
0x01,
0x01,
0x01,
0x04,
0x18,
0x05,
0x04, # third block, starts with UID
0x4D,
0x70,
0xBA,
0x5F,
0x35,
0x80,
0xBA,
0x44,
0x97,
0xD6,
0x70,
0x28,
0x13,
]
cv = CardVersion(data)
s = repr(cv)
assert "Hardware Version: 1.0" in s
assert "Software Version: 1.4" in s
print(s)


"""
output with current code was:
--- Desfire Card Details ---
Hardware Version: 0.0
Software Version: 1.4
EEPROM size: 8388608 bytes
Production: week 28, year 2013
UID no: 04 4D 70 BA 5F 35 80
Batch no: BA 44 97 D6

new code produces following output:
--- Desfire Card Details ---
Hardware Version: 1.0
Software Version: 1.4
EEPROM size: 4096 bytes
Production: week 28, year 2013
UID no: 04 4D 70 BA 5F 35 80
Batch no: BA 44 97 D6
"""