@@ -73,9 +73,89 @@ def memory_block_size(self) -> int:
7373
7474 @property
7575 def memory_number_of_blocks (self ) -> int :
76+ """Gets the number of blocks the card contains"""
7677 self ._ensure_sys_info_loaded ()
7778 return self ._num_blocks
7879
80+ def decode_cc (self , cc : bytes ) -> tuple [int , int , int , bool ] | None :
81+ """Decode the CC memory block (block 0)
82+
83+ Args:
84+ cc(bytes): The memory from block 0.
85+
86+ Returns:
87+ (major_version, minor_version, memory size, is readonly)
88+ or None if CC isn't valid.
89+
90+ Raises:
91+ PN5180Error: If communication with the card fails.
92+ ValueError: If cc is less than 4 bytes.
93+ """
94+ if len (cc ) < 4 :
95+ raise ValueError ("cc should be at least 4 bytes" )
96+
97+ if cc [0 ] != 0xE1 :
98+ return None
99+
100+ major = cc [1 ] >> 4
101+ minor = cc [1 ] & 0xF
102+
103+ mlen = (cc [2 ] + 1 ) * 8
104+
105+ is_readonly = bool (cc [3 ] & 1 )
106+
107+ return (major , minor , mlen , is_readonly )
108+
109+ def get_ndef (self , memory : bytes ) -> tuple [int , bytes ] | None :
110+ """Find the NDEF memory.
111+
112+ If found, the start index in the input memory and
113+ its bytes are returned.
114+
115+ Args:
116+ memory: The card's memory, starting from 0
117+
118+ Returns:
119+ (start, ndef_bytes),
120+ or None if it wasn't found.
121+ """
122+
123+ cc = self .decode_cc (memory )
124+ if cc is None :
125+ return None
126+
127+ major , _minor , mlen , _ = cc
128+
129+ if major > 4 :
130+ return None
131+
132+ if mlen > len (memory ):
133+ return None
134+
135+ pos = 4
136+
137+ def read_val (memory : bytes , pos : int ) -> tuple [int , int ]:
138+ if memory [pos ] < 255 :
139+ return memory [pos ], pos + 1
140+ else :
141+ return (memory [pos + 1 ] << 8 ) | memory [pos + 2 ], pos + 3
142+
143+ while pos < mlen :
144+ typ , pos = read_val (memory , pos )
145+ if typ == 0 :
146+ continue
147+ if typ == 0xFE :
148+ # End of TLV
149+ return None
150+ field_len , pos = read_val (memory , pos )
151+ if typ == 0x03 :
152+ if pos + field_len > mlen :
153+ return None
154+ return (pos , memory [pos :pos + field_len ])
155+ pos += field_len
156+
157+ return None
158+
79159 def read_memory (self , offset : int = 0 , length : int | None = None ) -> bytes :
80160 """Read memory from card.
81161
0 commit comments