Increase buffers a little and add better NDEF parsing.
7 files changed, 138 insertions(+), 70 deletions(-)

M avr-i2c.ads
M generic_pn532.adb
M ndef.adb
M ndef.ads
M nfc_tags.adb
M pm_strings.ads
M pn532_bus_i2c.adb
M avr-i2c.ads +2 -2
@@ 47,8 47,8 @@ package AVR.I2C is
 
    type I2C_Address is new Nat8 range 0 .. 127;
 
-   subtype Buffer_Index is Nat8 range 0 .. 81;
-   subtype Buffer_Range is Nat8 range 1 .. 81;
+   subtype Buffer_Index is Nat8 range 0 .. 90;
+   subtype Buffer_Range is Nat8 range 1 .. 90;
    type Data_Buffer is array (Buffer_Range range <>) of Nat8;
 
 end AVR.I2C;

          
M generic_pn532.adb +28 -37
@@ 28,6 28,8 @@ use Interfaces;
 
 package body Generic_PN532 is
 
+   Data_Buffer : PN532_Buf (1..90);
+
    PN532_FIRMWARE_VERSION : constant := 16#02#;
    PN532_SAMCONFIG        : constant := 16#14#;
    PN532_IN_LIST_PASSIVE_TARGET : constant := 16#4A#;

          
@@ 219,7 221,7 @@ package body Generic_PN532 is
                                  1, -- card number
                                  MIFARE_READ_CARD_CMD,
                                  0); -- Block number
-      Reply : PN532_Buf (1..40);
+      -- Reply : PN532_Buf (1..40);
       Reply_Len : Unsigned_8;
       Len   : Unsigned_8;
       Ok    : Boolean;

          
@@ 237,21 239,21 @@ package body Generic_PN532 is
          return;
       end if;
 
-      PN532_Read_Data (Reply, Reply_Len, Ok);
+      PN532_Read_Data (Data_Buffer, Reply_Len, Ok);
 
       if (not Ok) or (Reply_Len < 3) then
          Status := False;
          return;
       end if;
 
-      if Reply (2) /= 0 then -- status code not ok?
+      if Data_Buffer (2) /= 0 then -- status code not ok?
          Status := False;
          return;
       end if;
 
       Len := Unsigned_8'Min (Reply_Len - 3, Buf'Length);
       Byte_Count := Len;
-      Buf (1..Len) := Reply (3 .. Len + 2);
+      Buf (1..Len) := Data_Buffer (3 .. Len + 2);
 
       Status := True;
    end PN532_Read_NFC_Forum_Type_2_Tag_Block;

          
@@ 432,7 434,7 @@ package body Generic_PN532 is
                                   16#0C#, -- first or only occurrence
                                   16#02#, -- two bytes data
                                   Unsigned_8 (File_ID / 256), Unsigned_8 (File_ID and 16#FF#));
-      Reply : PN532_Buf (1..40);
+
       Reply_Len : Unsigned_8;
       Ok    : Boolean;
    begin

          
@@ 445,21 447,21 @@ package body Generic_PN532 is
          return False;
       end if;
 
-      PN532_Read_Data (Reply, Reply_Len, Ok);
+      PN532_Read_Data (Data_Buffer, Reply_Len, Ok);
 
       if (not Ok) or (Reply_Len < 5) then
          return False;
       end if;
 
-      if Reply (2) /= 0 then -- status code not ok?
+      if Data_Buffer (2) /= 0 then -- status code not ok?
          return False;
       end if;
 
-      if Reply (Reply_Len - 2) = 16#90# and Reply (Reply_Len - 1) = 16#00# then
+      if Data_Buffer (Reply_Len - 2) = 16#90# and Data_Buffer (Reply_Len - 1) = 16#00# then
          -- ok
          return True;
-      elsif Reply (Reply_Len - 2) = 16#6A#
-        and Reply (Reply_Len - 1) = 16#82#
+      elsif Data_Buffer (Reply_Len - 2) = 16#6A#
+        and Data_Buffer (Reply_Len - 1) = 16#82#
       then -- file not found
          return False;
       end if;

          
@@ 476,64 478,54 @@ package body Generic_PN532 is
       Byte_Count : out Unsigned_8;
       Status     : out Boolean)
    is
-      Cmd : PN532_Buf (1..7);
+      -- Data : PN532_Buf (1..90);
       Len : Unsigned_8;
-      Reply : PN532_Buf (1..70);
+      -- Reply : PN532_Buf (1..90);
       Reply_Len : Unsigned_8 := 0;
       Ok    : Boolean;
    begin
-      Len := Buf'Length;
-      if Len > Reply'Length then
-         Len := Reply'Length;
-      end if;
-      Cmd (1) := PN532_IN_DATA_EXCHANGE;
-      Cmd (2) := 1; -- card number
-      Cmd (3) := 16#00#; -- class
-      Cmd (4) := 16#B0#; -- instruction
-      Cmd (5) := Unsigned_8 (Offset and 16#FF#);
-      Cmd (6) := Unsigned_8 (Offset / 256);
-      Cmd (7) := Len;
+      Len := Unsigned_8'Min (Buf'Length, Data_Buffer'Length);
+      
+      Data_Buffer (1) := PN532_IN_DATA_EXCHANGE;
+      Data_Buffer (2) := 1; -- card number
+      Data_Buffer (3) := 16#00#; -- class
+      Data_Buffer (4) := 16#B0#; -- instruction
+      Data_Buffer (5) := Unsigned_8 (Offset and 16#FF#);
+      Data_Buffer (6) := Unsigned_8 (Offset / 256);
+      Data_Buffer (7) := Len;
 
-      Ok := PN532_Send_Command (Cmd, PN532_TIMEOUT_VALUE);
+      Ok := PN532_Send_Command (Data_Buffer (1..7), PN532_TIMEOUT_VALUE);
       if not Ok then
          Status := False;
          return;
       end if;
 
       if not PN532_Wait_For_Ready (PN532_TIMEOUT_VALUE * 30) then
-         Log ("read binary: timeout");
          Status := False;
          return;
       end if;
 
-      PN532_Read_Data (Reply, Reply_Len, Ok);
+      PN532_Read_Data (Data_Buffer, Reply_Len, Ok);
 
       if (not Ok) or (Reply_Len < 5) then
-         if not Ok then
-            Log ("read binary: not ok");
-         end if;
-         Log (Reply (1..Reply_Len));
          Status := False;
          return;
       end if;
 
-      if Reply (2) /= 0 then -- status code not ok?
-         Log ("status invalid");
+      if Data_Buffer (2) /= 0 then -- status code not ok?
          Status := False;
          return;
       end if;
 
-      if Reply (Reply_Len - 2) = 16#90# and Reply (Reply_Len - 1) = 16#00# then
+      if Data_Buffer (Reply_Len - 2) = 16#90# and Data_Buffer (Reply_Len - 1) = 16#00# then
          -- ok, copying buffer
 
          Len := Reply_Len - 5;
-         Buf (Buf'First .. Buf'First + Len) := Reply (3 .. 3 + Len);
+         Buf (Buf'First .. Buf'First + Len) := Data_Buffer (3 .. 3 + Len);
          Byte_Count := Len;
          Status := True;
       else
          Status := False;
-         -- Log ("read binary: reply invalid");
-         Log (Reply (1..Reply_Len));
          -- AVR.UART.Put ("Read failed"); AVR.UART.CRLF;
       end if;
    end PN532_NFC_Forum_Type_4_Read_Binary;

          
@@ 609,7 601,6 @@ package body Generic_PN532 is
       Reply_Len : Unsigned_8;
    begin
       if Buf'Length + Buf2'Length >= Cmd'Length - 2 then
-         -- Log ("PN532_Set_Data: Buf too big");
          return False;
       end if;
 

          
M ndef.adb +13 -13
@@ 77,7 77,7 @@ package body NDEF is
       Found    := False;
       Location := Pos;
    end Find_NDEF_TLV;
-   
+
 --   type NDEF_Record is record
 --      Message_Location : NDEF_Message_Location;
 --      Chunked : Boolean;

          
@@ 87,12 87,12 @@ package body NDEF is
 --      Payload_Offset : Interfaces.Unsigned_8;
 --      Payload_Length : Interfaces.Unsigned_8;
 --   end record;
-   
+
    -- Parse the NDEF record from the data
    -- Header format:
    --    MB|ME|CF|SR|IL|TNF
    --    Type Length
-   --    Payload len 4  
+   --    Payload len 4
    --    Payload len 3
    --    Payload len 2
    --    Payload len 1

          
@@ 109,7 109,7 @@ package body NDEF is
       SR_Mask     : constant Unsigned_8 := 2#0001_0000#;
       ID_Len_Mask : constant Unsigned_8 := 2#0000_1000#;
       TNF_Mask    : constant Unsigned_8 := 2#0000_0111#;
-      
+
       Current_Location : Unsigned_8 := Start;
       Type_Len : Unsigned_8;
       ID_Len : Unsigned_8 := 0;

          
@@ 118,21 118,21 @@ package body NDEF is
          Status := False;
          return;
       end if;
-      
+
       declare
          Header_Bits : constant Unsigned_8 := Data (Current_Location);
       begin
          NDEF_Header.Chunked := (Header_Bits and CF_Mask) = CF_Mask;
          NDEF_Header.Short_Record := (Header_Bits and SR_Mask) = SR_Mask;
          NDEF_Header.ID_Length_Present := (Header_Bits and ID_Len_Mask) = ID_Len_Mask;
-         NDEF_Header.TNF := To_TNF (ID_Len_Mask and TNF_Mask);
+         NDEF_Header.TNF := To_TNF (Header_Bits and TNF_Mask);
       end;
       Current_Location := Current_Location + 1;
-      
+
       -- Read Type length
       Type_Len := Data (Current_Location);
       Current_Location := Current_Location + 1;
-      
+
       -- Read Payload length
       if NDEF_Header.Short_Record then
          NDEF_Header.Payload_Length := Data (Current_Location);

          
@@ 142,7 142,7 @@ package body NDEF is
          return;
       end if;
       Current_Location := Current_Location + 1;
-      
+
       -- ID Length
       if NDEF_Header.ID_Length_Present then
          ID_Len := Data (Current_Location);

          
@@ 150,7 150,7 @@ package body NDEF is
       else
          ID_Len := 0;
       end if;
-     
+
       -- Type
       if Type_Len > 1 then -- types longer than 1 byte not supported
          Status := False;

          
@@ 159,12 159,12 @@ package body NDEF is
          NDEF_Header.NDEF_Type := Data (Current_Location);
       end if;
       Current_Location := Current_Location + 1;
-      
+
       -- ID, skip it
       Current_Location := Current_Location + ID_Len;
-      
+
       NDEF_Header.Payload_Offset := Current_Location;
-      
+
       Status := True;
       return;
    end Read_NDEF_Record;

          
M ndef.ads +3 -1
@@ 45,6 45,8 @@ package NDEF is
       TNF_RESERVED     => 7);
    function To_TNF is
      new Ada.Unchecked_Conversion (Interfaces.Unsigned_8, Type_Name_Format);
+   function TNF_To_Unsigned_8 is
+     new Ada.Unchecked_Conversion (Type_Name_Format, Interfaces.Unsigned_8);
 
    type NDEF_Record is record
       Message_Location : NDEF_Message_Location;

          
@@ 62,7 64,7 @@ package NDEF is
                             Location : out Interfaces.Unsigned_8;
                             TLV_Len  : out Interfaces.Unsigned_8;
                             Found    : out Boolean);
-                            
+
    procedure Read_NDEF_Record (Data        : NDEF_Array;
                                Start       : Interfaces.Unsigned_8;
                                NDEF_Header : out NDEF_Record;

          
M nfc_tags.adb +88 -16
@@ 48,6 48,53 @@ package body NFC_Tags is
       PN532_Read_Data => PN532_BUS_I2C.PN532_Read_Data);
 
    procedure Print_Str (Place : System.Address);
+   
+   procedure Print_NDEF_Record (NFC_Data    : PN532_Buf;
+                                NDEF_Header : NDEF.NDEF_Record)
+   is
+      use type NDEF.Type_Name_Format;
+
+      Data_End : Unsigned_8;
+   begin
+      Data_End := Unsigned_8'Min
+        (NFC_Data'Last,
+         NDEF_Header.Payload_Offset + NDEF_Header.Payload_Length - 1);
+      if Data_End < NDEF_Header.Payload_Offset + NDEF_Header.Payload_Length - 1 then
+         AVR.UART.Put ("Note: printing truncated");
+         AVR.UART.CRLF;
+         AVR.UART.Put (Data_End, 10);
+         AVR.UART.CRLF;
+         AVR.UART.Put (NDEF_Header.Payload_Offset + NDEF_Header.Payload_Length - 1, 10);
+         AVR.UART.CRLF;
+      end if;
+
+      AVR.UART.Put ("TNF: ");
+      AVR.UART.Put (Data => NDEF.TNF_To_Unsigned_8 (NDEF_Header.TNF), Base => 16);
+      AVR.UART.CRLF;
+      AVR.UART.Put ("NDEF record at ");
+      AVR.UART.Put (Data => NDEF_Header.Payload_Offset, Base => 10);
+      AVR.UART.CRLF;
+      AVR.UART.Put ("NDEF type: ");
+      AVR.UART.Put (Data => NDEF_Header.NDEF_Type, Base => 16);
+      AVR.UART.CRLF;
+      AVR.UART.Put ("NDEF Payload length: ");
+      AVR.UART.Put (Data => NDEF_Header.Payload_Length, Base => 10);
+      AVR.UART.CRLF;
+      
+      if NDEF_Header.TNF = NDEF.TNF_WELL_KNOWN then
+         if NDEF_Header.NDEF_Type = Character'Pos ('U') then
+            if NFC_Data (NDEF_Header.Payload_Offset) = 1 then -- https
+               AVR.UART.Put ("http://");
+            elsif NFC_Data (NDEF_Header.Payload_Offset) = 4 then -- https
+               AVR.UART.Put ("https://");
+            end if;
+            for I in NDEF_Header.Payload_Offset + 1 .. Data_End loop
+               AVR.UART.Put (Character'Val (NFC_Data (I)));
+            end loop;
+            AVR.UART.CRLF;
+         end if;
+      end if;
+   end Print_NDEF_Record;
 
    procedure Read_Mifare_Classic_Tag (NFC_ID : PN532_Buf) is
       Status : Boolean;

          
@@ 59,9 106,9 @@ package body NFC_Tags is
       NFC_Data : 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;
+--      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,

          
@@ 119,7 166,7 @@ package body NFC_Tags is
             NFC_Data (B*16 + 1 .. B*16 +16) := Data;
          end if;
 
-         AVR.UART.Put ("BLOCK ");
+         Print_Str(PM_Strings.BLOCK_PM'Address);
          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);

          
@@ 149,6 196,7 @@ package body NFC_Tags is
       Data : PN532_Buf (1 .. 16);
       NFC_Data : PN532_Buf (1 .. 48);
       NDEF_Loc : Unsigned_8 := 0;
+      NDEF_Header : NDEF.NDEF_Record;
    begin
       Print_Str (PM_Strings.Type_2_Tag_PM'Address); AVR.UART.CRLF;
       PN532.PN532_Read_NFC_Forum_Type_2_Tag_Block

          
@@ 172,8 220,7 @@ package body NFC_Tags is
          AVR.UART.Put (" bytes"); AVR.UART.CRLF;
 
          if Card_Block_Count > 50 then
-            AVR.UART.Put ("Reading first 50 blocks");
-            AVR.UART.CRLF;
+            -- Reading only the first 50 blocks
             Card_Block_Count := 50;
          end if;
 

          
@@ 194,7 241,7 @@ package body NFC_Tags is
                NFC_Data (B*16 + 1 .. B*16 +16) := Data;
             end if;
 
-            AVR.UART.Put ("BLOCK ");
+            Print_Str (PM_Strings.BLOCK_PM'Address);
             AVR.UART.Put (Data => (B + 1)*4, 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);

          
@@ 214,6 261,11 @@ package body NFC_Tags is
             AVR.UART.Put ("NDEF message at ");
             AVR.UART.Put (Data => NDEF_Loc, Base => 10);
             AVR.UART.CRLF;
+            
+            NDEF.Read_NDEF_Record (NDEF.NDEF_Array (NFC_Data), NDEF_Loc, NDEF_Header, Status);
+            if Status then
+               Print_NDEF_Record (NFC_Data, NDEF_Header);
+            end if;
          else
             AVR.UART.Put ("No NDEF TLV found");
             AVR.UART.CRLF;

          
@@ 222,7 274,6 @@ package body NFC_Tags is
          AVR.UART.Put ("Failed to read block from the tag");
          AVR.UART.CRLF;
       end if;
-
    end Read_Forum_Type_2_Tag;
 
    procedure Write_Forum_Type_2_Tag (Data : PN532_Buf) is

          
@@ 268,9 319,11 @@ package body NFC_Tags is
    end Write_Forum_Type_2_Tag;
 
    procedure Read_Forum_Type_4_Tag is
+      use type NDEF.Type_Name_Format;
+   
       Status : Boolean;
       Data : PN532_Buf (1 .. 16);
-      NFC_Data : PN532_Buf (1 .. 64);
+      NFC_Data : PN532_Buf (1 .. 80);
       Len : Unsigned_8;
       NDEF_ID : Unsigned_16;
       NDEF_Len : Unsigned_16;

          
@@ 331,16 384,35 @@ package body NFC_Tags is
          AVR.UART.Put (" ");
       end loop;
       AVR.UART.CRLF;
-      
+
       -- Read first record
       NDEF.Read_NDEF_Record (NDEF.NDEF_Array (NFC_Data), 3, NDEF_Header, Status);
       if Status then
-         AVR.UART.Put ("NDEF record at ");
-         AVR.UART.Put (Data => NDEF_Header.Payload_Offset, Base => 10);
-         AVR.UART.CRLF;
-         AVR.UART.Put ("NDEF type: ");
-         AVR.UART.Put (Data => NDEF_Header.NDEF_Type, Base => 16);
-         AVR.UART.CRLF;
+         Print_NDEF_Record (NFC_Data, NDEF_Header);
+--         AVR.UART.Put ("TNF: ");
+--         AVR.UART.Put (Data => NDEF.TNF_To_Unsigned_8 (NDEF_Header.TNF), Base => 16);
+--         AVR.UART.CRLF;
+--         AVR.UART.Put ("NDEF record at ");
+--         AVR.UART.Put (Data => NDEF_Header.Payload_Offset, Base => 10);
+--         AVR.UART.CRLF;
+--         AVR.UART.Put ("NDEF type: ");
+--         AVR.UART.Put (Data => NDEF_Header.NDEF_Type, Base => 16);
+--         AVR.UART.CRLF;
+--         AVR.UART.Put ("NDEF Payload length: ");
+--         AVR.UART.Put (Data => NDEF_Header.Payload_Length, Base => 10);
+--         AVR.UART.CRLF;
+--         
+--         if NDEF_Header.TNF = NDEF.TNF_WELL_KNOWN then
+--            if NDEF_Header.NDEF_Type = Character'Pos ('U') then
+--               if NFC_Data (NDEF_Header.Payload_Offset) = 4 then -- https
+--                  AVR.UART.Put ("https://");
+--               end if;
+--               for I in NDEF_Header.Payload_Offset + 1 .. (NDEF_Header.Payload_Offset + NDEF_Header.Payload_Length - 1) loop
+--                  AVR.UART.Put (Character'Val (NFC_Data (I)));
+--               end loop;
+--               AVR.UART.CRLF;
+--            end if;
+--         end if;
       else
          AVR.UART.Put ("Failed to parse NDEF record");
          AVR.UART.CRLF;

          
M pm_strings.ads +3 -0
@@ 38,6 38,7 @@ package PM_Strings is
    SAM_Failed_Str         : constant AVR.Strings.AVR_String := "SAM config FAILED";
    Type_2_Tag_Str         : constant AVR.Strings.AVR_String := "NFC Forum Type 2 tag";
    Type_4_Tag_Failed_Str  : constant AVR.Strings.AVR_String := "Failed to select type 4 tag";
+   BLOCK_Str              : constant AVR.Strings.AVR_String := "BLOCK ";
 
    Select_Action_PM : constant Text_In_Progmem := (Select_Action_Str'Length, Select_Action_Str);
    Read_NFC_PM      : constant Text_In_Progmem := (Read_NFC_Str'Length, Read_NFC_Str);

          
@@ 54,6 55,7 @@ package PM_Strings is
    SAM_Failed_PM     : constant Text_In_Progmem := (SAM_Failed_Str'Length, SAM_Failed_Str);
    Type_2_Tag_PM     : constant Text_In_Progmem := (Type_2_Tag_Str'Length, Type_2_Tag_Str);
    Type_4_Tag_Failed_PM : constant Text_In_Progmem := (Type_4_Tag_Failed_Str'Length, Type_4_Tag_Failed_Str);
+   BLOCK_PM          : constant Text_In_Progmem := (BLOCK_Str'Length, BLOCK_STR);
 
    pragma Linker_Section (Select_Action_PM, ".progmem");
    pragma Linker_Section (Read_NFC_PM, ".progmem");

          
@@ 70,4 72,5 @@ package PM_Strings is
    pragma Linker_Section (SAM_Failed_PM, ".progmem");
    pragma Linker_Section (Type_2_Tag_PM, ".progmem");
    pragma Linker_Section (Type_4_Tag_Failed_PM, ".progmem");
+   pragma Linker_Section (BLOCK_PM, ".progmem");
 end PM_Strings;

          
M pn532_bus_i2c.adb +1 -1
@@ 139,7 139,7 @@ package body PN532_BUS_I2C is
       Msg_Len : Unsigned_8;
       Ready_Status : Unsigned_8;
    begin
-      AVR.I2C.Master.Request (PN532_I2C_ADDRESS, 80);
+      AVR.I2C.Master.Request (PN532_I2C_ADDRESS, AVR.I2C.Buffer_Range'Last);
       
       loop
          exit when AVR.I2C.Master.Data_Is_Available;