Use the new authentication procedure for Mifare tags.
3 files changed, 130 insertions(+), 3 deletions(-)

M nfc_main.adb
M pn532.adb
M pn532.ads
M nfc_main.adb +107 -1
@@ 30,6 30,91 @@ package body NFC_Main is
 
    procedure Print_Str (Place : System.Address);
 
+   procedure Read_Mifare_Classic_Tag (NFC_ID : PN532.PN532_Buf) is
+      Status : Boolean;
+      Key_A : PN532.PN532_Buf_6 := (255, 255, 255, 255, 255, 255);
+      MAD_Key_A : PN532.PN532_Buf_6 :=
+        (16#A0#, 16#A1#,  16#A2#, 16#A3#, 16#A4#, 16#A5#);
+      Key_B : PN532.PN532_Buf_6 := (255, 255, 255, 255, 255, 255);
+      Data : PN532.PN532_Buf (1 .. 16);
+      NFC_Data : PN532.PN532_Buf (1 .. 48);
+      Len : Unsigned_8;
+   begin
+      AVR.UART.Put ("UID len: ");
+      AVR.UART.Put (Unsigned_8 (NFC_ID'Length), 10);
+      AVR.UART.CRLF;
+      PN532.PN532_Authenticate_Mifare_Classic_Tag_Block
+        (Block_Number => 0,
+         UID          => NFC_ID,
+         Key          => PN532.AUTH_A,
+         Key_Data     => MAD_Key_A,
+         Status       => Status);
+      if Status then
+         AVR.UART.Put ("Classic tag auth OK");
+         AVR.UART.CRLF;
+      else
+         AVR.UART.Put ("Classic tag auth FAILED");
+         AVR.UART.CRLF;
+      end if;
+
+      if False then
+         PN532.PN532_Read_NFC_Forum_Type_2_Tag_Block
+          (Block => 0,
+           Buf   => Data,
+           Byte_Count => Len,
+           Status => Status);
+         if Status then
+            AVR.UART.Put ("BLOCK 00: ");
+            for I in Unsigned_8 range 1 .. Len loop
+               AVR.UART.Put (Data => Data (I), Base => 16);
+               AVR.UART.Put (" ");
+            end loop;
+            AVR.UART.CRLF;
+         else
+            AVR.UART.Put ("Read failed");
+            AVR.UART.CRLF;
+         end if;
+      end if;
+      for B in Unsigned_8 range 0 .. 7 loop
+
+         if B mod 4 = 0 and B > 0 then
+            PN532.PN532_Authenticate_Mifare_Classic_Tag_Block
+              (Block_Number => B,
+               UID          => NFC_ID,
+               Key          => PN532.AUTH_B,
+               Key_Data     => Key_B,
+               Status       => Status);
+         end if;
+         PN532.PN532_Read_NFC_Forum_Type_2_Tag_Block
+           (Block => B, -- (B + 1)*4,
+            Buf   => Data,
+            Byte_Count => Len,
+            Status => Status);
+         if not Status then
+            AVR.UART.Put ("Failed to read block ");
+            AVR.UART.Put (Data => B, Base => 16);
+            AVR.UART.CRLF;
+            exit;
+         end if;
+         if B*16 + 16 < NFC_Data'Last then
+            NFC_Data (B*16 + 1 .. B*16 +16) := Data;
+         end if;
+
+         AVR.UART.Put ("BLOCK ");
+         AVR.UART.Put (Data => B, Base => 16);
+         AVR.UART.Put (" from "); AVR.UART.Put (B*16 +1, Base => 10);
+         AVR.UART.Put (" to "); AVR.UART.Put (B*16 + 16, Base => 10);
+         AVR.UART.Put (": ");
+         for I in Unsigned_8 range 1 .. Len loop
+            AVR.UART.Put (Data => Data (I), Base => 16);
+            AVR.UART.Put (" ");
+         end loop;
+         AVR.UART.CRLF;
+      end loop;
+
+
+   end Read_Mifare_Classic_Tag;
+
    -- Read NFC Forum type 2 tag (like NXP Mifare Ultralight or NXP NTAG)
    --
    -- First 4 blocks are special */

          
@@ 302,6 387,8 @@ package body NFC_Main is
    procedure Read_Tag is
       Sel_Res  : Unsigned_8;
       Sens_Res : Unsigned_16;
+      NFC_ID   : PN532.PN532_Buf (1..16);
+      NFC_ID_Len : Unsigned_8;
       Status   : Boolean;
    begin
       AVR.UART.Put ("Reading NFC tag");

          
@@ 312,16 399,31 @@ package body NFC_Main is
       loop
          PN532.PN532_Detect_Tag (Sens_Res => Sens_Res,
                                  Sel_Res => Sel_Res,
+                                 NFC_ID => NFC_ID,
+                                 NFC_ID_Len => NFC_ID_Len,
                                  Status => Status);
          if Status then
             -- NFC Forum type 2 tag
             if Sel_Res = 16#00# and Sens_Res = 16#4400# then
                Read_Forum_Type_2_Tag;
             -- NFC Forum type 4 tag
+            elsif Sel_Res = 16#08# and Sens_Res = 16#0400# then
+               AVR.UART.Put ("Mifare classic tag MF1S503");
+               AVR.UART.CRLF;
+               Read_Mifare_Classic_Tag
+                 (NFC_ID (NFC_ID'First..NFC_ID'First + NFC_ID_Len - 1));
+            elsif Sel_Res = 16#08# and Sens_Res = 16#4400# then
+               AVR.UART.Put ("Mifare classic tag MF1S500");
+               AVR.UART.CRLF;
+               Read_Mifare_Classic_Tag
+                 (NFC_ID (NFC_ID'First..NFC_ID'First + NFC_ID_Len - 1));
             elsif Sel_Res = 16#20# and Sens_Res = 16#4403# then
                Read_Forum_Type_4_Tag;
             else
-               AVR.UART.Put ("Unknown tag detected");
+               AVR.UART.Put ("Unknown tag detected: ");
+               AVR.UART.Put (Sel_Res, 16);
+               AVR.UART.Put (" ");
+               AVR.UART.Put (Sens_Res, 16);
                AVR.UART.CRLF;
             end if;
 

          
@@ 352,6 454,8 @@ package body NFC_Main is
       Ch : Character;
       Len : Unsigned_8 := 0;
       My_String : PN532.PN532_Buf (1..8);
+      NFC_ID : PN532.PN532_Buf (1..7);
+      NFC_ID_Len : Unsigned_8;
       Sel_Res  : Unsigned_8;
       Sens_Res : Unsigned_16;
       Status   : Boolean;

          
@@ 387,6 491,8 @@ package body NFC_Main is
       loop
          PN532.PN532_Detect_Tag (Sens_Res => Sens_Res,
                                  Sel_Res => Sel_Res,
+                                 NFC_ID => NFC_ID,
+                                 NFC_ID_Len => NFC_ID_Len,
                                  Status => Status);
          if Status then
             -- NFC Forum type 2 tag

          
M pn532.adb +21 -2
@@ 333,6 333,8 @@ package body PN532 is
    procedure PN532_Detect_Tag
      (Sens_Res : out Unsigned_16;
       Sel_Res : out Unsigned_8;
+      NFC_ID  : out PN532_Buf;
+      NFC_ID_Len : out Unsigned_8;
       Status : out Boolean)
    is
       Cmd : PN532_Buf (1..3) :=

          
@@ 372,6 374,12 @@ package body PN532 is
       Sens_Res := Unsigned_16 (Reply (5)) * 256 or Unsigned_16 (Reply (4));
       Sel_Res := Reply (6);
 
+      NFC_ID_Len := Reply (7);
+      if NFC_ID_Len > NFC_ID'Length then
+         NFC_ID_Len := NFC_ID'Length;
+      end if;
+      NFC_ID := Reply (8..7 + NFC_ID_Len);
+
       Status := Ok;
    end PN532_Detect_Tag;
 

          
@@ 486,30 494,41 @@ package body PN532 is
       Cmd (4) := Unsigned_8 (Block_Number);
       Cmd (5..4 + Key_Data'Length) := Key_Data;
       if UID'Length > 10 then
+         Log ("UID too big");
          Status := False;
          return;
       end if;
       Cmd (11..10 + UID'Length) := UID;
 
-      Ok := PN532_Send_Command (Cmd, PN532_TIMEOUT_VALUE);
+      Log (Cmd (1..10+UID'Length));
+      Ok := PN532_Send_Command (Cmd (1..10+UID'Length), PN532_TIMEOUT_VALUE);
       if not Ok then
+         Log ("Send command failed");
          Status := False;
          return;
       end if;
 
       if not PN532_Wait_For_Ready (PN532_TIMEOUT_VALUE) then
+         Log ("timeout");
          Status := False;
          return;
       end if;
 
       PN532_Read_Data (Reply, Reply_Len, Ok);
+      Log ("Reply:");
+      Log (Reply (1..Reply_Len));
 
       if (not Ok) or (Reply_Len < 3) then
+         Log ("Read data failed");
          Status := False;
          return;
       end if;
 
-      if Reply (2) /= 0 then -- status code not ok?
+      if Reply (2) = 16#14# then -- Mifare authentication error
+         Log ("Mifare auth error");
+         Status := False;
+         return;
+      elsif Reply (2) /= 0 then -- status code not ok?
          Status := False;
          return;
       end if;

          
M pn532.ads +2 -0
@@ 38,6 38,8 @@ package PN532 is
    procedure PN532_Detect_Tag
      (Sens_Res : out Interfaces.Unsigned_16;
       Sel_Res  : out Interfaces.Unsigned_8;
+      NFC_ID  : out PN532_Buf;
+      NFC_ID_Len : out Interfaces.Unsigned_8;
       Status   : out Boolean);
 
    procedure PN532_Authenticate_Mifare_Classic_Tag_Block