libpcscada-0.7.1/0000755000175000017500000000000011664137641012275 5ustar reetreetlibpcscada-0.7.1/tests/0000755000175000017500000000000011664137641013437 5ustar reetreetlibpcscada-0.7.1/tests/pcsc-scard-tests.ads0000644000175000017500000000327611664137641017322 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ahven.Framework; -- Test package for PCSC.SCard functions and procedures. package PCSC.SCard.Tests is type Test is new Ahven.Framework.Test_Case with null record; procedure Initialize (T : in out Test); -- Initialize Test suite. procedure Test_Slice_Readerstring; -- Test Slice_Readerstring function. procedure Test_To_Ada_Proto; -- Test Thin.DWORD to Proto conversion. procedure Test_To_C_RCond_Set; -- Test Reader_Condition_Set to Thin.READERSTATE_Array conversion. procedure Test_To_Card_States_Set; -- Test Thin.DWORD to Card_States_Set conversion. procedure Test_To_Chars_Ptr; -- Test Reader_ID to chars_ptr conversion. procedure Test_To_Reader_States_Set; -- Test Thin.DWORD to Reader_States_Set conversion. procedure Bytes_To_Atr; -- Verify byte set to ATR conversion. end PCSC.SCard.Tests; libpcscada-0.7.1/tests/test_pcscada.adb0000644000175000017500000002523511664137641016553 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with Ada.Strings.Fixed; with PCSC.Version; with PCSC.SCard.Utils; use PCSC; -- PCSC/Ada integration test procedure. To run these tests, you need to have -- at least one reader and one smartcard ready. -- -- To ease comparing test runs, this procedure is implemented in a manner -- similar to the pcsc-lite 'testpcsc' test binary, which should be used as -- test reference. procedure Test_PCSCAda is pragma Linker_Options ("-lpcsclite"); package SCU renames SCard.Utils; Context : SCard.Context; Card : SCard.Card; Readers : SCard.Reader_ID_Set; Reader_Table : SCard.Reader_Condition_Set; Reader1 : SCard.Reader_Condition; begin Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("** PCSC/Ada Thick-Binding test program [version " & PCSC.Version.Version_String & "] **"); Ada.Text_IO.New_Line; -- Establish context SCU.Action_Info (Text => "Testing Establish_Context"); SCard.Establish_Context (Context => Context, Scope => SCard.Scope_System); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Test for valid context SCU.Action_Info (Text => "Testing Is_Valid"); if not SCard.Is_Valid (Context => Context) then SCU.Action_Result (Result => "FAILED : " & SCard.Get_Return_Code); end if; SCU.Action_Result (Result => SCard.Get_Return_Code); -- Wait for first reader to appear Ada.Text_IO.Put_Line ("Testing Wait_For_Readers"); SCU.Action_Info (Text => "Please connect a reader"); SCard.Wait_For_Readers (Context => Context); SCU.Action_Result (Result => SCard.Get_Return_Code); -- List readers SCU.Action_Info (Text => "Testing List_Readers"); Readers := SCard.List_Readers (Context => Context); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line ("> Readers found : "); SCU.For_Every_Reader (Readers => Readers, Call => SCU.Print_ReaderID'Access); -- Use first reader for status change detection. Reader1.Name := Readers.First_Item; Reader1.Current_State.Add (State => SCard.S_Reader_Empty); Reader_Table.Add (Status => Reader1); -- Detect status changes SCU.Action_Info (Text => "Waiting for card insertion"); SCard.Status_Change (Context => Context, Conditions => Reader_Table); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> Reader Name : " & SCU.To_String (Reader_Table.Get (Index => 1).Name)); Ada.Text_IO.Put_Line (">> Reader states : " & SCU.To_String (Reader_Table.Get (Index => 1).Event_State)); Ada.Text_IO.Put_Line (">> Card ATR : " & SCU.To_Hex_String (Reader_Table.Get (Index => 1).Card_ATR)); -- Connect to first reader SCU.Action_Info (Text => "Testing Connect"); SCard.Connect (Context => Context, Card => Card, Reader => Readers.First_Item, Mode => SCard.Share_Shared); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> Card uses protocol : " & SCard.Proto'Image (SCard.Get_Active_Proto (Card => Card))); -- Begin transaction with first reader SCU.Action_Info (Text => "Testing Begin_Transaction"); SCard.Begin_Transaction (Card => Card); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Test status declare Card_States : SCard.Card_States_Set; Card_Proto : SCard.Proto := SCard.Proto_Undefined; Card_ATR : SCard.ATR; begin SCU.Action_Info (Text => "Testing Status"); SCard.Status (Card => Card, State => Card_States, Proto => Card_Proto, Atr => Card_ATR); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> ATR : " & SCU.To_Hex_String (Given => Card_ATR)); Ada.Text_IO.Put_Line (">> ATR Size : " & SCard.Size (Card_ATR)); Ada.Text_IO.Put_Line (">> Protocol : " & SCard.Proto'Image (Card_Proto)); Ada.Text_IO.Put_Line (">> Card states : " & SCU.To_String (Card_States)); end; -- Send arbitrary APDU to card declare Recv_Buffer : SCard.Byte_Set (1 .. 10); Send_Buffer : constant SCard.Byte_Set := (16#00#, 16#A4#, 16#00#, 16#00#, 16#02#, 16#3F#, 16#00#); Recv_Len : Natural := 0; Recv_PCI : SCard.IO_Request; begin SCU.Action_Info (Text => "Testing Transmit"); SCard.Transmit (Card => Card, Send_Buffer => Send_Buffer, Recv_Pci => Recv_PCI, Recv_Buffer => Recv_Buffer, Recv_Len => Recv_Len); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> APDU (select file) : " & SCU.To_Hex_String (Given => Send_Buffer)); Ada.Text_IO.Put_Line (">> Response from card : " & SCU.To_Hex_String (Given => Recv_Buffer, Len => 2 * Recv_Len)); end; -- Test smart card control declare Recv_Buffer : SCard.Byte_Set (1 .. 10); Send_Buffer : constant SCard.Byte_Set := (16#06#, 16#00#, 16#0A#, 16#01#, 16#01#, 16#10#, 16#00#); Recv_Len : Natural := 0; Control_Code : constant := 16#42000001#; begin SCU.Action_Info (Text => "Testing Control"); SCard.Control (Card => Card, Code => Control_Code, Send_Buffer => Send_Buffer, Recv_Buffer => Recv_Buffer, Recv_Len => Recv_Len); SCU.Action_Result (Result => SCard.Get_Return_Code); exception when SCard_Error => -- This test is allowed to fail SCU.Action_Result (Result => "FAILED (don't PANIC): " & SCard.Get_Return_Code); end; -- Test Get_Attribute SCU.Action_Info (Text => "Testing Get_Attribute"); begin declare Attr_Vendor : SCard.Byte_Set := SCard.Init_Attribute_Set (Card => Card, Attr => SCard.Attr_Vendor_Name); Attr_ATR : SCard.Byte_Set := SCard.Init_Attribute_Set (Card => Card, Attr => SCard.Attr_ATR_String); Attr_Maxinput : SCard.Byte_Set := SCard.Init_Attribute_Set (Card => Card, Attr => SCard.Attr_Maxinput); use Ada.Strings.Fixed; begin SCard.Get_Attribute (Card => Card, Attr => SCard.Attr_Vendor_Name, Recv_Buffer => Attr_Vendor); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> Attr_Vendor_Name is : " & SCU.To_String (Given => Attr_Vendor)); Ada.Text_IO.Put_Line (">> Attr_Vendor_Name size : " & Trim (Source => Attr_Vendor'Last'Img, Side => Ada.Strings.Left)); SCU.Action_Info (Text => "Testing Get_Attribute"); SCard.Get_Attribute (Card => Card, Attr => SCard.Attr_ATR_String, Recv_Buffer => Attr_ATR); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> Attr_ATR_String is : " & SCU.To_Hex_String (Given => Attr_ATR)); Ada.Text_IO.Put_Line (">> Attr_ATR_String size : " & Trim (Source => Attr_ATR'Last'Img, Side => Ada.Strings.Left)); SCU.Action_Info (Text => "Testing Get_Attribute"); SCard.Get_Attribute (Card => Card, Attr => SCard.Attr_Maxinput, Recv_Buffer => Attr_Maxinput); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.Put_Line (">> Attr_Maxinput is : " & Trim (Source => SCU.To_Long_Long_Integer (Given => Attr_Maxinput)'Img, Side => Ada.Strings.Left)); end; exception when SCard_Error => -- Most likely this happens when GetAttribute feature is not -- supported by the ifd handler of the reader. SCU.Action_Result (Result => "FAILED (don't PANIC): " & SCard.Get_Return_Code); end; -- End transaction with first reader SCU.Action_Info (Text => "Testing End_Transaction"); SCard.End_Transaction (Card => Card, Action => SCard.Leave_Card); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Reconnect to first reader SCU.Action_Info (Text => "Testing Reconnect"); SCard.Reconnect (Card => Card, Mode => SCard.Share_Shared, Action => SCard.Unpower_Card); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Disconnect from first reader SCU.Action_Info (Text => "Testing Disconnect"); SCard.Disconnect (Card => Card, Action => SCard.Unpower_Card); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Release context SCU.Action_Info (Text => "Testing Release_Context"); SCard.Release_Context (Context => Context); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("PCSC/Ada test completed successfully!"); Ada.Text_IO.New_Line; exception when others => SCU.Action_Result (Result => "FAILED: " & SCard.Get_Return_Code); if SCard.Is_Valid (Context => Context) then SCard.Release_Context (Context => Context); end if; raise; end Test_PCSCAda; libpcscada-0.7.1/tests/tests_utils.ads0000644000175000017500000000343111664137641016513 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ahven.Framework; -- Test package for PCSC.SCard.Utils functions/procedures. package Tests_Utils is type Test is new Ahven.Framework.Test_Case with null record; procedure Initialize (T : in out Test); -- Initialize Test suite. procedure Test_ATR_To_Hex_String; -- Test ATR to HEX String conversion. procedure Test_BArray_To_Hex_String; -- Test Byte_Array to HEX String conversion. procedure Test_BSet_To_Hex_String; -- Test Byte_Set to HEX String conversion. procedure Test_Byte_Set_To_String; -- Test Byte_Set to String conversion. procedure Test_CStates_Set_To_String; -- Test Card_States_Set to String conversion. procedure Test_RStates_Set_To_String; -- Test Reader_States_Set to String conversion. procedure Test_ReaderID_To_String; -- Test Reader_ID to String conversion. procedure Test_To_Long_Long_Integer; -- Test Byte_Set to Long_Long_Integer conversion. end Tests_Utils; libpcscada-0.7.1/tests/runner.adb0000644000175000017500000000245211664137641015423 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ahven.Framework; with Ahven.Text_Runner; with Tests_Utils; with PCSC.SCard.Tests; procedure Runner is pragma Linker_Options ("-lpcsclite"); S : constant Ahven.Framework.Test_Suite_Access := Ahven.Framework.Create_Suite (Suite_Name => "PCSC/Ada Unit Tests"); begin S.Add_Test (T => new Tests_Utils.Test); S.Add_Test (T => new PCSC.SCard.Tests.Test); Ahven.Text_Runner.Run (Suite => S); Ahven.Framework.Release_Suite (T => S); end Runner; libpcscada-0.7.1/tests/pcsc-scard-tests.adb0000644000175000017500000003334711664137641017303 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Characters.Latin_1; with Ahven; use Ahven; with Interfaces.C.Strings; with PCSC.SCard.Utils; with PCSC.SCard.Conversion; package body PCSC.SCard.Tests is package Convert renames PCSC.SCard.Conversion; ------------------------------------------------------------------------- procedure Bytes_To_Atr is Valid_1 : constant Byte_Set (5 .. 37) := (others => 0); Valid_2 : constant Byte_Set (0 .. 32) := (others => 0); Valid_3 : constant Byte_Set (5 .. 7) := (others => 2); Valid_4 : constant Byte_Set := Null_Byte_Set; Too_Long : constant Byte_Set (1 .. 34) := (others => 0); Tmp_ATR : ATR; Ref_ATR_3 : constant ATR := ATR' (Data => ATR_Data_Type' (0 => 2, 1 => 2, 2 => 2, others => Thin.Null_Byte), Size => 3); begin Tmp_ATR := To_Atr (Bytes => Valid_1); Assert (Condition => Size (Atr => Tmp_ATR) = 33, Message => "Valid_1 not 33 bytes"); Tmp_ATR := To_Atr (Bytes => Valid_2); Assert (Condition => Size (Atr => Tmp_ATR) = 33, Message => "Valid_2 not 33 bytes"); Tmp_ATR := To_Atr (Bytes => Valid_3); Assert (Condition => Size (Atr => Tmp_ATR) = 3, Message => "Valid_3 not 3 bytes"); Assert (Condition => Tmp_ATR = Ref_ATR_3, Message => "Valid_3 ATR mismatch"); Tmp_ATR := To_Atr (Bytes => Valid_4); Assert (Condition => Size (Atr => Tmp_ATR) = 0, Message => "Valid_4 not 0 bytes"); begin Tmp_ATR := To_Atr (Bytes => Too_Long); Fail (Message => "Expected bytes to big error"); exception when Bytes_Too_Big => null; end; end Bytes_To_Atr; ------------------------------------------------------------------------- procedure Initialize (T : in out Test) is begin T.Set_Name (Name => "Tests for SCard package"); T.Add_Test_Routine (Routine => Test_Slice_Readerstring'Access, Name => "String to Reader_ID_Set"); T.Add_Test_Routine (Routine => Test_To_C_RCond_Set'Access, Name => "To_C for Reader_Condition_Set"); T.Add_Test_Routine (Routine => Test_To_Chars_Ptr'Access, Name => "Reader_ID to LPSTR"); T.Add_Test_Routine (Routine => Test_To_Ada_Proto'Access, Name => "DWORD to Proto type"); T.Add_Test_Routine (Routine => Test_To_Card_States_Set'Access, Name => "DWORD to Card_States_Set"); T.Add_Test_Routine (Routine => Test_To_Reader_States_Set'Access, Name => "DWORD to Reader_States_Set"); T.Add_Test_Routine (Routine => Bytes_To_Atr'Access, Name => "Byte set to ATR"); end Initialize; ------------------------------------------------------------------------- procedure Test_Slice_Readerstring is use type Ada.Containers.Count_Type; use type VOIDP.Vector; -- Separation and Termination chars Sep : constant Character := Ada.Characters.Latin_1.NUL; Term : constant String := Ada.Characters.Latin_1.NUL & Ada.Characters.Latin_1.NUL; -- Input sources Source1 : constant String := "This is not a reader string"; Source2 : constant String := "One Reader" & Term; Source3 : constant String := "First Reader" & Sep & "_SecondReader_" & Sep & " Third _ Reader II " & Term; -- Resulting reader ID set Readers : Reader_ID_Set; begin -- Test slicing of an ordinary, invalid string Readers := Convert.Slice_Readerstring (To_Slice => Source1); Assert (Condition => Readers.Data = VOIDP.Empty_Vector, Message => "Reader_ID_Set not empty"); -- Test slicing of one reader Readers := Convert.Slice_Readerstring (To_Slice => Source2); Assert (Condition => Readers.Data.Length = 1, Message => "Slicing failed"); Assert (Condition => Readers.First_Item = "One Reader", Message => "Reader name does not match"); -- Test slicing of multiple readers Readers := Convert.Slice_Readerstring (To_Slice => Source3); Assert (Condition => Readers.Data.Length = 3, Message => "Slicing failed"); Assert (Condition => Readers.First_Item = "First Reader", Message => "Reader name does not match"); Assert (Condition => Readers.Get (Index => 2) = "_SecondReader_", Message => "Reader name does not match"); Assert (Condition => Readers.Last_Item = " Third _ Reader II ", Message => "Reader name does not match"); end Test_Slice_Readerstring; ------------------------------------------------------------------------- procedure Test_To_Ada_Proto is No_Proto : constant Thin.DWORD := 16#FFFF_FFFF#; RAW : constant Thin.DWORD := Thin.SCARD_PROTOCOL_RAW; begin Assert (Condition => Convert.To_Ada (C_Protocol => No_Proto) = Proto_Undefined, Message => "Proto not Proto_Undefined"); -- Just test one Thin.DWORD to Proto conversion, no need to test all Assert (Condition => Convert.To_Ada (C_Protocol => RAW) = Proto_RAW, Message => "Proto not Proto_RAW"); end Test_To_Ada_Proto; ------------------------------------------------------------------------- procedure Test_To_C_RCond_Set is -- Empty set test Empty_Set : Reader_Condition_Set; -- This should return an empty array E_Result : constant Thin.READERSTATE_Array := Convert.To_C (Conditions => Empty_Set); -- Construct a 'real' condition set Real_Set : Reader_Condition_Set; Reader1 : Reader_Condition; Reader2 : Reader_Condition; Useless : Reader_States_Set; begin -- Empty Assert (Condition => E_Result'Length = 0, Message => "array not empty"); -- Fill real set Reader1.Name := To_Reader_ID ("Reader I"); Reader1.Current_State.Add (State => S_Reader_Unavailable); Reader2.Name := To_Reader_ID ("Reader II"); Reader2.Current_State.Add (State => S_Reader_Unaware); -- Setting Event_State of Reader2 should be ignored by the conversion, -- defaults are used instead. Settting Event_State manually makes no -- sense since they are updated by calling the Status_Change procedure. Useless.Add (State => S_Reader_Ignore); Useless.Add (State => S_Reader_Exclusive); Reader2.Event_State := Useless; Reader2.Card_ATR := To_Atr (Bytes => Byte_Set'(16#12#, 16#23#)); -- Add reader status to set set Real_Set.Add (Status => Reader1); Real_Set.Add (Status => Reader2); declare use Thin; use Interfaces.C; R_Result : Thin.READERSTATE_Array := Convert.To_C (Conditions => Real_Set); begin -- Test resulting size of array Assert (Condition => R_Result'Length = 2, Message => "array size mismatch"); -- Test individual values one by one -- szReader names Assert (Condition => String'(Strings.Value (R_Result (R_Result'First).szReader)) = "Reader I", Message => "reader name mismatch"); Assert (Condition => String'(Strings.Value (R_Result (R_Result'Last).szReader)) = "Reader II", Message => "reader name mismatch"); -- pvUserData must be null Assert (Condition => R_Result (R_Result'First).pvUserData = null, Message => "pvUserData not null"); Assert (Condition => R_Result (R_Result'Last).pvUserData = null, Message => "pvUserData not null"); -- dwCurrentState Assert (Condition => R_Result (R_Result'First).dwCurrentState = SCARD_STATE_UNAVAILABLE, Message => "dwCurrentState incorrect"); Assert (Condition => R_Result (R_Result'Last).dwCurrentState = SCARD_STATE_UNAWARE, Message => "dwCurrentState incorrect"); -- dwEventState must be set to default, even though we specified -- Reader_States_Set 'Useless' above. Assert (Condition => R_Result (R_Result'First).dwEventState = 0, Message => "dwEventState incorrect"); Assert (Condition => R_Result (R_Result'Last).dwEventState = 0, Message => "dwEventState incorrect"); -- cbAtr value must match Card_ATR.Data'Length Assert (Condition => R_Result (R_Result'First).cbAtr = Reader1.Card_ATR.Data'Length, Message => "cbAtr size incorrect"); Assert (Condition => R_Result (R_Result'Last).cbAtr = Reader2.Card_ATR.Data'Length, Message => "cbAtr size incorrect"); -- rgbAtr (Byte_Array) must match Card_ATR.Data for Reader2 and -- Null_ATR for Reader1 Assert (Condition => ATR_Data_Type (Byte_Set (R_Result (R_Result'First).rgbAtr)) = Null_ATR.Data, Message => "ATR data mismatch"); Assert (Condition => ATR_Data_Type (Byte_Set (R_Result (R_Result'Last).rgbAtr)) = Reader2.Card_ATR.Data, Message => "ATR data mismatch"); -- Free memory after test Convert.Free (Name => R_Result); end; end Test_To_C_RCond_Set; ------------------------------------------------------------------------- procedure Test_To_Card_States_Set is use VOCSP; use type Interfaces.C.unsigned_long; use type Ada.Containers.Count_Type; No_CSet : constant Thin.DWORD := 0; S3_Set : constant Thin.DWORD := Thin.SCARD_UNKNOWN + Thin.SCARD_ABSENT + Thin.SCARD_SWALLOWED; Real_Set : constant Card_States_Set := Convert.To_Ada (C_Cardstate => S3_Set); begin Assert (Condition => Convert.To_Ada (C_Cardstate => No_CSet).Data = Empty_Vector, Message => "CStates_Set not empty"); -- Test converted Real_Set Assert (Condition => Real_Set.Data.Length = 3, Message => "Expected 3 Card_States"); -- Negative test first Assert (Condition => Real_Set.Data.Find (Item => S_Card_Powered) = No_Element, Message => "Invalid state found"); Assert (Condition => Real_Set.Data.Find (Item => S_Card_Unknown) /= No_Element, Message => "Card_Powered not found"); Assert (Condition => Real_Set.Data.Find (Item => S_Card_Absent) /= No_Element, Message => "Card_Absent not found"); Assert (Condition => Real_Set.Data.Find (Item => S_Card_Swallowed) /= No_Element, Message => "Card_Swallowed not found"); end Test_To_Card_States_Set; ------------------------------------------------------------------------- procedure Test_To_Chars_Ptr is use Interfaces.C; ID : constant Reader_ID := To_Reader_ID (Name => "Reader I"); Ptr : Strings.chars_ptr := Convert.To_Chars_Ptr (Reader => ID); begin Assert (Condition => String'(Strings.Value (Item => Ptr)) = Utils.To_String (Reader => ID), Message => "Reader name mismatch"); -- Free memory Strings.Free (Item => Ptr); end Test_To_Chars_Ptr; ------------------------------------------------------------------------- procedure Test_To_Reader_States_Set is use VORSP; use type Interfaces.C.unsigned_long; use type Ada.Containers.Count_Type; No_RSet : constant Thin.DWORD := 0; S3_Set : constant Thin.DWORD := Thin.SCARD_STATE_PRESENT + Thin.SCARD_STATE_EXCLUSIVE + Thin.SCARD_STATE_IGNORE; Real_Set : constant Reader_States_Set := Convert.To_Ada (C_Readerstate => S3_Set); begin Assert (Condition => Convert.To_Ada (C_Readerstate => No_RSet).Data = VORSP.Empty_Vector, Message => "RStates_Set not empty"); -- Test converted Real_Set Assert (Condition => Real_Set.Data.Length = 3, Message => "Expected 3 Reader_States"); -- Negative test first Assert (Condition => Real_Set.Data.Find (Item => S_Reader_Empty) = No_Element, Message => "Invalid state found"); Assert (Condition => Real_Set.Data.Find (Item => S_Reader_Present) /= No_Element, Message => "Reader_Present not found"); Assert (Condition => Real_Set.Data.Find (Item => S_Reader_Exclusive) /= No_Element, Message => "Reader_Exclusive not found"); Assert (Condition => Real_Set.Data.Find (Item => S_Reader_Ignore) /= No_Element, Message => "Reader_Ignore not found"); end Test_To_Reader_States_Set; end PCSC.SCard.Tests; libpcscada-0.7.1/tests/tests_utils.adb0000644000175000017500000002023511664137641016473 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ahven; use Ahven; with PCSC.Thin; with PCSC.SCard.Utils; use PCSC; package body Tests_Utils is package SCU renames SCard.Utils; ------------------------------------------------------------------------- procedure Initialize (T : in out Test) is begin T.Set_Name (Name => "Tests for SCard.Utils package"); T.Add_Test_Routine (Routine => Test_To_Long_Long_Integer'Access, Name => "Byte_Set to Long_Long_Integer"); T.Add_Test_Routine (Routine => Test_Byte_Set_To_String'Access, Name => "Byte_Set to String"); T.Add_Test_Routine (Routine => Test_RStates_Set_To_String'Access, Name => "Reader_States_Set to String"); T.Add_Test_Routine (Routine => Test_CStates_Set_To_String'Access, Name => "Card_States_Set to String"); T.Add_Test_Routine (Routine => Test_ReaderID_To_String'Access, Name => "Reader_ID to String"); T.Add_Test_Routine (Routine => Test_ATR_To_Hex_String'Access, Name => "ATR to HEX String"); T.Add_Test_Routine (Routine => Test_BArray_To_Hex_String'Access, Name => "Byte_Array to HEX String"); T.Add_Test_Routine (Routine => Test_BSet_To_Hex_String'Access, Name => "Byte_Set to HEX String"); end Initialize; ------------------------------------------------------------------------- procedure Test_ATR_To_Hex_String is Null_ATR : constant SCard.ATR := SCard.Null_ATR; ATR_Bytes : constant SCard.Byte_Set := (16#2C#, 16#23#, 16#AB#, 16#8B#); Reader_ATR : constant SCard.ATR := SCard.To_Atr (Bytes => ATR_Bytes); begin Assert (Condition => SCU.To_Hex_String (Given => Null_ATR) = "0", Message => "Null Hex string incorrect"); Assert (Condition => SCU.To_Hex_String (Given => Reader_ATR) = "2C23AB8B", Message => "Hex string incorrect"); end Test_ATR_To_Hex_String; ------------------------------------------------------------------------- procedure Test_BArray_To_Hex_String is Empty_Array : constant Thin.Byte_Array := Thin.Null_Byte_Array; Real_Array : constant Thin.Byte_Array := (16#2C#, 16#FF#, 16#78#, 16#AF#); begin Assert (Condition => SCU.To_Hex_String (Given => Empty_Array, Len => 1234) = "0", Message => "Hex string not '0'"); Assert (Condition => SCU.To_Hex_String (Given => Real_Array, Len => 2 * Real_Array'Length) = "2CFF78AF", Message => "Hex string incorrect"); end Test_BArray_To_Hex_String; ------------------------------------------------------------------------- procedure Test_BSet_To_Hex_String is Empty_Set : constant SCard.Byte_Set := SCard.Null_Byte_Set; Real_Set : constant SCard.Byte_Set := (16#00#, 16#A4#, 16#00#, 16#00#, 16#02#, 16#3F#, 16#00#); begin Assert (Condition => SCU.To_Hex_String (Given => Empty_Set) = "0", Message => "Hex string not '0'"); Assert (Condition => SCU.To_Hex_String (Given => Real_Set) = "00A40000023F00", Message => "Hex string incorrect"); end Test_BSet_To_Hex_String; ------------------------------------------------------------------------- procedure Test_Byte_Set_To_String is Empty_Set : constant SCard.Byte_Set := SCard.Null_Byte_Set; Test_Set : constant SCard.Byte_Set (1 .. 4) := (16#70#, 16#63#, 16#73#, 16#63#); begin Assert (Condition => SCU.To_String (Given => Empty_Set) = "0", Message => "Returned string not '0'"); Assert (Condition => SCU.To_String (Given => Test_Set) = "pcsc", Message => "Returned string not 'pcsc'"); Assert (Condition => SCU.To_String (Given => Test_Set, Len => 2) = "pc", Message => "Returned string not 'pc'"); Assert (Condition => SCU.To_String (Given => Test_Set, Len => 6) = "pcsc", Message => "Returned string not 'pcsc'"); end Test_Byte_Set_To_String; ------------------------------------------------------------------------- procedure Test_CStates_Set_To_String is Empty_CStates : SCard.Card_States_Set; CStates : SCard.Card_States_Set; begin Assert (Condition => SCU.To_String (States => Empty_CStates)'Length = 0, Message => "String not empty"); -- Fill CStates set CStates.Add (State => SCard.S_Card_Swallowed); CStates.Add (State => SCard.S_Card_Powered); Assert (Condition => SCU.To_String (States => CStates) = "S_CARD_POWERED S_CARD_SWALLOWED", Message => "String incorrect"); end Test_CStates_Set_To_String; ------------------------------------------------------------------------- procedure Test_ReaderID_To_String is Null_Reader : constant SCard.Reader_ID := SCard.Null_Reader_ID; begin Assert (Condition => SCU.To_String (Reader => Null_Reader)'Length = 0, Message => "String incorrect"); end Test_ReaderID_To_String; ------------------------------------------------------------------------- procedure Test_RStates_Set_To_String is Empty_RStates : SCard.Reader_States_Set; RStates : SCard.Reader_States_Set; begin Assert (Condition => SCU.To_String (States => Empty_RStates)'Length = 0, Message => "String not empty"); -- Fill RStates set RStates.Add (State => SCard.S_Reader_Unaware); RStates.Add (State => SCard.S_Reader_Atrmatch); Assert (Condition => SCU.To_String (States => RStates) = "S_READER_ATRMATCH S_READER_UNAWARE", Message => "String incorrect"); end Test_RStates_Set_To_String; ------------------------------------------------------------------------- procedure Test_To_Long_Long_Integer is Null_Set : constant SCard.Byte_Set := SCard.Null_Byte_Set; Small_Set : constant SCard.Byte_Set (1 .. 2) := (16#12#, 16#FF#); Big_Set : constant SCard.Byte_Set (1 .. 4) := (16#AA#, 16#0A#, 16#BA#, 16#12#); Result : Long_Long_Integer; begin -- Null_Byte_Set Result := SCU.To_Long_Long_Integer (Given => Null_Set); Assert (Condition => Result = 0, Message => "result is not 0"); -- Big byte set Result := SCU.To_Long_Long_Integer (Given => Big_Set); Assert (Condition => Result = 314182314, Message => "result is not 314182314"); -- Small byte set Result := SCU.To_Long_Long_Integer (Given => Small_Set); Assert (Condition => Result = 65298, Message => "result is not 65298"); declare Set_Too_Big : constant SCard.Byte_Set (1 .. 8) := (16#FF#, 16#FF#, 16#FF#, 16#FF#, 16#FF#, 16#FF#, 16#FF#, 16#FF#); begin -- Byte set 'Set_Too_Big' cannot be represented by -- Long_Long_Integer, this test should raise Number_Too_Big exception Result := SCU.To_Long_Long_Integer (Given => Set_Too_Big); Fail (Message => "No Number_Too_Big exception raised"); exception when Bytes_Too_Big => null; end; end Test_To_Long_Long_Integer; end Tests_Utils; libpcscada-0.7.1/AUTHORS0000644000175000017500000000003711664137641013345 0ustar reetreetReto Buerki libpcscada-0.7.1/doc/0000755000175000017500000000000011664137641013042 5ustar reetreetlibpcscada-0.7.1/doc/.gitignore0000644000175000017500000000002711664137641015031 0ustar reetreethtml/*.html html/*.css libpcscada-0.7.1/doc/asciidoc.css0000644000175000017500000002364111664137641015340 0ustar reetreetbody { font-family: Georgia,serif; } h1, h2, h3, h4, h5, h6, div.title, caption.title, thead, p.table.header, #toctitle, #author, #revnumber, #revdate, #revremark, #footer { font-family: Arial,Helvetica,sans-serif; } body { background-color: #f1f1f1; } table.main { width: 80%; margin: 1em 10% 1em 10%; background: none repeat scroll 0 0 #ffffff; -webkit-border-radius: 10px; -webkit-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.6); -moz-border-radius: 10px; -moz-box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.6); border-radius: 10px; box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.6); } td.header { background-color: #666262; padding: 1px 15px 1px; border-bottom: 5px solid #4183c4; -webkit-border-top-left-radius: 10px; -webkit-border-top-right-radius: 10px; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; } td.content { padding: 1px 15px 40px; } td.footer { background-color: #666262; border-top: 8px solid #4183c4; -webkit-border-bottom-right-radius: 10px; -webkit-border-bottom-left-radius: 10px; -moz-border-radius-bottomright: 10px; -moz-border-radius-bottomleft: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; } a { outline: none; } a:link, a:visited { color: #4183c4; text-decoration: none; } a:hover { text-decoration: underline; } em { font-style: italic; color: gray; } strong { font-weight: bold; color: #083194; } h2, h3, h4, h5, h6 { color: #4183c4; margin-top: 1.2em; margin-bottom: 0.5em; line-height: 1.3; } h1 { color: white; } h2, h3 { border-bottom: 1px solid silver; } h2 { padding-top: 0.5em; } h3 { float: left; } h3 + * { clear: left; } h5 { font-size: 1.0em; } div.sectionbody { margin-left: 0; } hr { border: 1px solid silver; } p { margin-top: 0.5em; margin-bottom: 0.5em; } ul, ol, li > p { margin-top: 0; } ul > li { color: #aaa; } ul > li > * { color: black; } pre { padding: 0; margin: 0; } #author { color: #527bbd; font-weight: bold; font-size: 1.1em; } #email { } #revnumber, #revdate, #revremark { } #footer { font-size: x-small; margin-bottom: 4.0em; } #footer-text { color: #f1f1f1; float: right; padding-bottom: 0.5em; margin-right: 4px; } #footer-badges { float: right; padding-bottom: 0.5em; } #preamble { margin-top: 1.5em; margin-bottom: 1.5em; } div.imageblock, div.exampleblock, div.verseblock, div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock, div.admonitionblock { margin-top: 1.0em; margin-bottom: 1.5em; } div.admonitionblock { margin-top: 2.0em; margin-bottom: 2.0em; margin-right: 10%; color: #606060; } div.content { /* Block element content. */ padding: 0; } /* Block element titles. */ div.title, caption.title { color: #527bbd; font-weight: bold; text-align: left; margin-top: 1.0em; margin-bottom: 0.5em; } div.title + * { margin-top: 0; } td div.title:first-child { margin-top: 0.0em; } div.content div.title:first-child { margin-top: 0.0em; } div.content + div.title { margin-top: 0.0em; } div.sidebarblock > div.content { background: #ffffee; border: 1px solid #dddddd; border-left: 4px solid #f0f0f0; padding: 0.5em; } div.listingblock > div.content { border: 1px solid #dddddd; border-left: 5px solid #f0f0f0; background: #f8f8f8; padding: 0.5em; } div.quoteblock, div.verseblock { padding-left: 1.0em; margin-left: 1.0em; margin-right: 10%; border-left: 5px solid #f0f0f0; color: #888; } div.quoteblock > div.attribution { padding-top: 0.5em; text-align: right; } div.verseblock > pre.content { font-family: inherit; font-size: inherit; } div.verseblock > div.attribution { padding-top: 0.75em; text-align: left; } /* DEPRECATED: Pre version 8.2.7 verse style literal block. */ div.verseblock + div.attribution { text-align: left; } div.admonitionblock .icon { vertical-align: top; font-size: 1.1em; font-weight: bold; text-decoration: underline; color: #527bbd; padding-right: 0.5em; } div.admonitionblock td.content { padding-left: 0.5em; border-left: 3px solid #dddddd; } div.exampleblock > div.content { border-left: 3px solid #dddddd; padding-left: 0.5em; } div.imageblock div.content { padding-left: 0; } span.image img { border-style: none; } a.image:visited { color: white; } dl { margin-top: 0.8em; margin-bottom: 0.8em; } dt { margin-top: 0.5em; margin-bottom: 0; font-style: normal; color: gray; } dd > *:first-child { margin-top: 0.1em; } ul, ol { list-style-position: outside; } ol.arabic { list-style-type: decimal; } ol.loweralpha { list-style-type: lower-alpha; } ol.upperalpha { list-style-type: upper-alpha; } ol.lowerroman { list-style-type: lower-roman; } ol.upperroman { list-style-type: upper-roman; } div.compact ul, div.compact ol, div.compact p, div.compact p, div.compact div, div.compact div { margin-top: 0.1em; margin-bottom: 0.1em; } tfoot { font-weight: bold; } td > div.verse { white-space: pre; } div.hdlist { margin-top: 0.8em; margin-bottom: 0.8em; } div.hdlist tr { padding-bottom: 15px; } dt.hdlist1.strong, td.hdlist1.strong { font-weight: bold; } td.hdlist1 { vertical-align: top; font-style: normal; padding-right: 0.8em; color: gray; } td.hdlist2 { vertical-align: top; } div.hdlist.compact tr { margin: 0; padding-bottom: 0; } .comment { background: yellow; } .footnote, .footnoteref { font-size: 0.8em; } span.footnote, span.footnoteref { vertical-align: super; } #footnotes { margin: 20px 0 20px 0; padding: 7px 0 0 0; } #footnotes div.footnote { margin: 0 0 5px 0; } #footnotes hr { border: none; border-top: 1px solid silver; height: 1px; text-align: left; margin-left: 0; width: 20%; min-width: 100px; } div.colist td { padding-right: 0.5em; padding-bottom: 0.3em; vertical-align: top; } div.colist td img { margin-top: 0.3em; } @media print { #footer-badges { display: none; } } #toc { margin-bottom: 2.5em; } #toctitle { color: #527bbd; font-size: 1.1em; font-weight: bold; margin-top: 1.0em; margin-bottom: 0.1em; } div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 { margin-top: 0; margin-bottom: 0; } div.toclevel2 { margin-left: 2em; font-size: 0.9em; } div.toclevel3 { margin-left: 4em; font-size: 0.9em; } div.toclevel4 { margin-left: 6em; font-size: 0.9em; } span.aqua { color: aqua; } span.black { color: black; } span.blue { color: blue; } span.fuchsia { color: fuchsia; } span.gray { color: gray; } span.green { color: green; } span.lime { color: lime; } span.maroon { color: maroon; } span.navy { color: navy; } span.olive { color: olive; } span.purple { color: purple; } span.red { color: red; } span.silver { color: silver; } span.teal { color: teal; } span.white { color: white; } span.yellow { color: yellow; } span.aqua-background { background: aqua; } span.black-background { background: black; } span.blue-background { background: blue; } span.fuchsia-background { background: fuchsia; } span.gray-background { background: gray; } span.green-background { background: green; } span.lime-background { background: lime; } span.maroon-background { background: maroon; } span.navy-background { background: navy; } span.olive-background { background: olive; } span.purple-background { background: purple; } span.red-background { background: red; } span.silver-background { background: silver; } span.teal-background { background: teal; } span.white-background { background: white; } span.yellow-background { background: yellow; } span.big { font-size: 2em; } span.small { font-size: 0.6em; } span.underline { text-decoration: underline; } span.overline { text-decoration: overline; } span.line-through { text-decoration: line-through; } /* * xhtml11 specific * * */ tt { font-family: monospace; font-size: inherit; color: gray; } div.tableblock { margin-top: 1.0em; margin-bottom: 1.5em; } div.tableblock > table { border: 3px solid #527bbd; } thead, p.table.header { font-weight: bold; color: #527bbd; } p.table { margin-top: 0; } /* Because the table frame attribute is overriden by CSS in most browsers. */ div.tableblock > table[frame="void"] { border-style: none; } div.tableblock > table[frame="hsides"] { border-left-style: none; border-right-style: none; } div.tableblock > table[frame="vsides"] { border-top-style: none; border-bottom-style: none; } /* * html5 specific * * */ .monospaced { font-family: monospace; font-size: inherit; color: gray; } table.tableblock { margin-top: 1.0em; margin-bottom: 1.5em; } thead, p.tableblock.header { font-weight: bold; color: #527bbd; } p.tableblock { margin-top: 0; } table.tableblock { border-width: 3px; border-spacing: 0px; border-style: solid; border-color: #527bbd; border-collapse: collapse; } th.tableblock, td.tableblock { border-width: 1px; padding: 4px; border-style: solid; border-color: #527bbd; } table.tableblock.frame-topbot { border-left-style: hidden; border-right-style: hidden; } table.tableblock.frame-sides { border-top-style: hidden; border-bottom-style: hidden; } table.tableblock.frame-none { border-style: hidden; } th.tableblock.halign-left, td.tableblock.halign-left { text-align: left; } th.tableblock.halign-center, td.tableblock.halign-center { text-align: center; } th.tableblock.halign-right, td.tableblock.halign-right { text-align: right; } th.tableblock.valign-top, td.tableblock.valign-top { vertical-align: top; } th.tableblock.valign-middle, td.tableblock.valign-middle { vertical-align: middle; } th.tableblock.valign-bottom, td.tableblock.valign-bottom { vertical-align: bottom; } /* * manpage specific * * */ body.manpage h1 { padding-top: 0.5em; padding-bottom: 0.5em; border-top: 2px solid silver; border-bottom: 2px solid silver; } body.manpage h2 { border-style: none; } body.manpage div.sectionbody { margin-left: 3em; } @media print { body.manpage div#toc { display: none; } } libpcscada-0.7.1/doc/page.conf0000644000175000017500000004660311664137641014636 0ustar reetreet[miscellaneous] outfilesuffix=.html [attributes] basebackend=html basebackend-html= basebackend-xhtml11= [replacements2] # Line break. (?m)^(.*)\s\+$=\1
[replacements] ifdef::asciidoc7compatible[] # Superscripts. \^(.+?)\^=\1 # Subscripts. ~(.+?)~=\1 endif::asciidoc7compatible[] [ruler-blockmacro]
[pagebreak-blockmacro]
[blockdef-pass] asciimath-style=template="asciimathblock",subs=[] latexmath-style=template="latexmathblock",subs=[] [macros] # math macros. # Special characters are escaped in HTML math markup. (?su)[\\]?(?Pasciimath|latexmath):(?P\S*?)\[(?P.*?)(?asciimath|latexmath)::(?P\S*?)(\[(?P.*?)\])$=#[specialcharacters] [asciimath-inlinemacro] `{passtext}` [asciimath-blockmacro]
{title}
`{passtext}`
[asciimathblock]
{title}
`|`
[latexmath-inlinemacro] {passtext} [latexmath-blockmacro]
{title}
{passtext}
[latexmathblock]
{title}
|
[image-inlinemacro] {data-uri%}{alt={target}} {data-uri#}{alt={target}} {link#} [image-blockmacro]
{caption={figure-caption} {counter:figure-number}. }{title}
[unfloat-blockmacro]
[indexterm-inlinemacro] # Index term. {empty} [indexterm2-inlinemacro] # Index term. # Single entry index term that is visible in the primary text flow. {1} [footnote-inlinemacro] # footnote:[].
[{0}]
[footnoteref-inlinemacro] # footnoteref:[], create reference to footnote. {2%}
[{1}]
# footnoteref:[,], create footnote with ID. {2#}
[{2}]
[callout-inlinemacro] ifndef::icons[] <{index}> endif::icons[] ifdef::icons[] ifndef::data-uri[] {index} endif::data-uri[] ifdef::data-uri[] {index} endif::data-uri[] endif::icons[] # Comment line macros. [comment-inlinemacro] {showcomments#}
{passtext}
[comment-blockmacro] {showcomments#}

{passtext}

[literal-inlinemacro] # Inline literal. {passtext} # List tags. [listtags-bulleted] list=
{title?
{title}
}
    |
item=
  • |
  • text=

    |

    [listtags-numbered] # The start attribute is not valid XHTML 1.1 but all browsers support it. list=
    {title?
    {title}
    }
      |
    item=
  • |
  • text=

    |

    [listtags-labeled] list=
    {title?
    {title}
    }
    |
    entry= label= term=
    |
    item=
    |
    text=

    |

    [listtags-horizontal] list=
    {title?
    {title}
    }{labelwidth?}{itemwidth?}|
    label=| term=|
    entry=| item=| text=

    |

    [listtags-qanda] list=
    {title?
    {title}
    }
      |
    entry=
  • |
  • label= term=

    |

    item= text=

    |

    [listtags-callout] ifndef::icons[] list=
    {title?
    {title}
    }
      |
    item=
  • |
  • text=

    |

    endif::icons[] ifdef::icons[] list=
    {title?
    {title}
    }|
    ifndef::data-uri[] item={listindex}| endif::data-uri[] ifdef::data-uri[] item={listindex}| endif::data-uri[] text=| endif::icons[] [listtags-glossary] list=
    {title?
    {title}
    }
    |
    label= entry= term=
    |
    item=
    |
    text=

    |

    [listtags-bibliography] list=
    {title?
    {title}
    }
      |
    item=
  • |
  • text=

    |

    [tags] # Quoted text. emphasis={1?}|{1?} strong={1?}|{1?} monospaced={1?}|{1?} singlequoted={lsquo}{1?}|{1?}{rsquo} doublequoted={ldquo}{1?}|{1?}{rdquo} unquoted={1?}|{1?} superscript={1?}|{1?} subscript={1?}|{1?} ifdef::deprecated-quotes[] # Override with deprecated quote attributes. emphasis={role?}|{role?} strong={role?}|{role?} monospaced={role?}|{role?} singlequoted={role?}{1,2,3?}{amp}#8216;|{amp}#8217;{1,2,3?}{role?} doublequoted={role?}{1,2,3?}{amp}#8220;|{amp}#8221;{1,2,3?}{role?} unquoted={role?}{1,2,3?}|{1,2,3?}{role?} superscript={role?}|{role?} subscript={role?}|{role?} endif::deprecated-quotes[] # Inline macros [http-inlinemacro] {0={name}:{target}} [https-inlinemacro] {0={name}:{target}} [ftp-inlinemacro] {0={name}:{target}} [file-inlinemacro] {0={name}:{target}} [irc-inlinemacro] {0={name}:{target}} [mailto-inlinemacro] {0={target}} [link-inlinemacro] {0={target}} [callto-inlinemacro] {0={target}} # anchor:id[text] [anchor-inlinemacro] # [[id,text]] [anchor2-inlinemacro] # [[[id]]] [anchor3-inlinemacro] [{1}] # xref:id[text] [xref-inlinemacro] {0=[{target}]} # <> [xref2-inlinemacro] {2=[{1}]} # Special word substitution. [emphasizedwords] {words} [monospacedwords] {words} [strongwords] {words} # Paragraph substitution. [paragraph]
    {title?
    {title}
    }

    |

    [admonitionparagraph] template::[admonitionblock] # Delimited blocks. [listingblock]
    {caption=}{title}
    
    |
    
    [literalblock]
    {title}
    
    |
    
    [sidebarblock]
    {title}
    |
    [openblock]
    {title}
    |
    [partintroblock] template::[openblock] [abstractblock] template::[quoteblock] [quoteblock]
    {title}
    |
    {citetitle}{attribution?
    } — {attribution}
    [verseblock]
    {title}
    |
    
    {citetitle}{attribution?
    } — {attribution}
    [exampleblock]
    {caption={example-caption} {counter:example-number}. }{title}
    |
    [admonitionblock]
    {data-uri%}{icons#}{caption} {data-uri#}{icons#}{caption} {icons%}
    {caption}
    {title}
    |
    # Tables. [tabletags-default] colspec= bodyrow=| headdata=| bodydata=| paragraph=

    |

    [tabletags-header] paragraph=

    |

    [tabletags-emphasis] paragraph=

    |

    [tabletags-strong] paragraph=

    |

    [tabletags-monospaced] paragraph=

    |

    [tabletags-verse] bodydata=
    |
    paragraph= [tabletags-literal] bodydata=
    |
    paragraph= [tabletags-asciidoc] bodydata=
    |
    paragraph= [table]
    {colspecs} {headrows#} {headrows} {headrows#} {footrows#} {footrows} {footrows#} {bodyrows}
    {caption={table-caption} {counter:table-number}. }{title}
    #-------------------------------------------------------------------- [floatingtitle] {title} [preamble] # Untitled elements between header and first section title.
    |
    # Document sections. [sect0] {title} | [sect1]
    {numbered?{sectnum} }{title}
    |
    [sect2]
    {numbered?{sectnum} }{title} |
    [sect3]
    {numbered?{sectnum} }{title} |
    [sect4]
    {title} |
    [appendix]
    {numbered?{sectnum} }{appendix-caption} {counter:appendix-number:A}: {title}
    |
    [toc]
    {toc-title}
    [header] {title} {title%}{doctitle=} ifdef::linkcss[] ifdef::quirks[] endif::quirks[] ifdef::pygments[] ifdef::toc2[] endif::linkcss[] ifndef::linkcss[] endif::linkcss[] ifndef::disable-javascript[] ifdef::linkcss[] endif::linkcss[] ifndef::linkcss[] endif::linkcss[] endif::disable-javascript[] ifdef::asciimath[] ifdef::linkcss[] endif::linkcss[] ifndef::linkcss[] endif::linkcss[] endif::asciimath[] ifdef::latexmath[] ifdef::linkcss[] endif::linkcss[] ifndef::linkcss[] endif::linkcss[] endif::latexmath[] {docinfo1,docinfo2#}{include:{docdir}/docinfo.html} {docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.html} template::[docinfo]
    # Article, book header. ifndef::doctype-manpage[]
    endif::doctype-manpage[] # Man page header. ifdef::doctype-manpage[] endif::doctype-manpage[]
    [footer]
    ifdef::doctype-manpage[] [synopsis] template::[sect1] endif::doctype-manpage[] ifdef::quirks[] include::xhtml11-quirks.conf[] endif::quirks[] libpcscada-0.7.1/doc/Makefile0000644000175000017500000000110411664137641014476 0ustar reetreetDESTDIR ?= html STYLEPATH ?= . PREPARE := $(shell mkdir -p $(DESTDIR)) ASCIIDOC_OPTS = \ --backend=xhtml11 \ --conf-file=page.conf \ -a stylesdir=$(STYLEPATH) \ -a linkcss \ -a disable-javascript \ -o - all: $(DESTDIR)/asciidoc.css build_page $(DESTDIR)/asciidoc.css: asciidoc.css cp $< $@ build_page: asciidoc $(ASCIIDOC_OPTS) index > $(DESTDIR)/index.html asciidoc $(ASCIIDOC_OPTS) ../README > $(DESTDIR)/README.html asciidoc $(ASCIIDOC_OPTS) ../CHANGELOG > $(DESTDIR)/CHANGELOG.html clean: rm -f $(DESTDIR)/*.html rm -f $(DESTDIR)/*.css PHONY: build_page libpcscada-0.7.1/doc/index0000644000175000017500000000347311664137641014103 0ustar reetreetPCSC/Ada Library ================ link:README.html[README] link:CHANGELOG.html[CHANGELOG] http://www.codelabs.ch/download[Download] Introduction ------------ The PCSC/Ada library provides bindings to PC/SC-middleware for the Ada programming language. The library allows you to communicate with smart cards using the SCard API with Ada. PC/SC is a specification for SmartCard integration in computing environment. PC/SC is implemented in Microsoft Windows 200x/XP and available under Microsoft Windows NT/9x. A free implementation of PC/SC, PC/SC Lite, is available under Linux and bundled with Mac OS X. Overview and Examples --------------------- PCSC/Ada provides a thin and a thick binding for the PC/SC API. The thin binding is not explained here though, since Ada programmers should not use this binding directly. It is much more convenient to use the thick binding provided by the `PCSC.SCard` package. The following code is used to demonstrate how to establish a PC/SC context, connect to the first reader of a sytem and then send some arbitrary command to the smart card: [source,ada] --------------------------------------------------------------------- include::../examples/sample/sample.adb[] --------------------------------------------------------------------- For more detailed examples on how to use PC/SC Ada in your own applications, examine the sample applications which are included in the distribution tarball `examples` directory (for information about the included examples, check the link:README.html#_examples[Examples section] in the README). API documentation ----------------- - You can find the API documentation of PCSC/Ada online http://www.codelabs.ch/pcscada/api[here]. Browse the source ----------------- - You can browse the PCSC/Ada source code with gitweb http://git.codelabs.ch/?p=pcscada.git[here]. libpcscada-0.7.1/CHANGELOG0000644000175000017500000010316511664137641013515 0ustar reetreetPCSC/Ada ChangeLog ================== Version 0.7.1 (2011-11-26) -------------------------- .Additions and changes * Doc: Remove unneeded Makefile targets (77059b5) * Link to online API doc on index page (2fcc762) * Simplify doc build (7cd1147) * Don't include doc and pcsc-version.ads in tarball (82ec7a7) - No need to pre-generate these files as they are either automatically created by make or manually on user request (make doc). * Remove DOCDIR on distclean (f6bafbf) * Add doc/.gitignore file (6069761) * Introduce software revision number (826e0a9) - The next release will be 0.7.1 * Doc: Remove unneeded emphasis on 'thick' (1ee575f) * Doc: Replace navy color with gray (c5e4660) * Doc: Add -webkit and -moz border config (79d0e24) * Doc: Introduce fancy header, footer (353e252) * Doc: Update stylesheet (336c42a) * Doc: Disable badges (8850888) * Doc: Use custom asciidoc config file (7b93f5c) * Rename alog.css to asciidoc.css (a0de971) * Update README file (152b007) * Doc: Remove unneeded -a icons command-line option (6225c99) * Doc: Remove TIP from README (7b00728) * Update README file (1ce8d7f) * Make apidoc and doc independent targets (32d0f71) * Remove unneeded copyright section from README (07481dd) * Makefile: Add target to build doc/apidoc (493a10f) * Doc: Auto-build pcscada webpage using asciidoc (6ba8785) * Rename docs target to apidoc (a70edad) * Install API doc into doc/html/api directory (31d76d7) Version 0.7 (2011-08-23) ------------------------ .Additions and changes * Update CHANGELOG for release 0.7. (7fe7f01) * Add lib and obj subdirs to gitignore. (4365106) * Simplify Compiler_Switches. (44d2826) * Update copyright headers. (7547034) * Update README file. (7291f2d) * Bump MINOR version to 7. (c7f76d0) * Unify test names. (5f20f26) * Transmit: Remove send buffer default expression. (950f2b2) * Correctly handle byte sets not starting at index 1. (e3f0dfc) * Introduce internal ATR_Byte_Count type. (bf54072) * Status_Change: Reset ATR data on card removal. (996ac00) * Add exception handler to status peeker. (a27de6a) * Rename ATR_Type to ATR_Data_Type. (acb1b94) * Allow ATR size of 33 bytes. (e7c20f4) - According to ISO 7816-3, the answer to reset is at most 33 characters (including the initial character). * Transmit: Return optional recv PCI data to caller. (dd4ff89) - Thanks to Stefan Berghofer for the hint. * Provide additional Transmit procedure. (279cde9) - This procedure transmits Send_Len bytes of the given buffer to the card. * Minor: Fix indentation. (45d1165) * Use 79 in line length checks (-gnatyM79). (5cef8b1) * SCU: Add To_String() function with Len parameter. (027ce74) - This function converts Len bytes from byte set to string. * SCardSetAttrib: Use Byte_Array type for pbAttr. (09a4aa6) * Remove obsolete TODO in Init_Attribute_Set(). (f106d71) * Make SCardTransmit() a Valued_Procedure. (6fe7bc7) * Make SCardStatus() a Valued_Procedure. (3b60575) * Minor: Fix Null_Byte constant alignment. (260f688) * SCardTransmit: Use Byte_Array type for pbSendBuffer. (e6688b9) - See Ada RM B.3/70: An Ada parameter of an array type with component type T, of any mode, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. * Use Natural range instead of C.size_t for Byte_Array. (178a422) * Remove unneeded type conversions. (6b27e9d) * Minor: More code cleanup in examples. (e255c7b) * Minor: Remove unnecessary spaces in thin example. (db37035) * Minor: Remove unnecessary spaces in test output. (57fb476) * Fix Library_Name in IFD example project file. (a3cf804) * Add IFD handler example. (cdb6d17) * Add initial Thin.IFDHandler package. (18ae12d) * Add UCHAR, PDWORD and ATR_Access (sub)types. (af1d7a2) * Minor code cleanup. (f9a6bc4) * Remove unnecessary comment. (3227dcc) * Minor: Correct indentation in pcsc-version file. (1651809) Version 0.6 (2010-01-13) ------------------------ .Additions and changes * Update CHANGELOG for release 0.6. (bc52668) * Remove 'git describe' version string. (3baf31c) * Don't force pcscada-git-rev target. (a8f911e) * Remove pcscada.specs in docs target. (bf94d81) * Update README file. (3e85b9d) * Add sample code. (c7e188a) * Use dotted notation for ahven code. (4c6fec0) * Replace box comments by dashed line separators. (defea84) * Bump MINOR version to 6. (4de4606) * Remove unneeded Builder packages from project files. (840c76f) * Remove unneeded -fPIC from Compiler_Switches. (81a954d) * Use 'git describe' for GIT_REV. (38d7c53) * Add library kind selection support to build logic. (2d9d121) * Remove explicit 'in' parameter mode. (19b9f26) * Use common settings in library project too. (f374432) * Remove apidoc directory on distclean. (110be42) * Let gnatmake create missing dirs. (2a6cbdf) * Add Detect_Blocking pragma. (b18c2f8) * Factor out common settings to PCSCAda_Common. (3b4daf8) * Remove unneeded Linker_Options ("-lahven"). (c3f9a84) * Add missing ahven dependency to project file. (8819653) * Link libpcscada (dynamic) against pcsclite. (9d857fa) * Don't remove generated pcsc-version.ads file on distclean. (f872703) * Add another TODO item. (6c13873) * Change examples project name to PCSCAda_Examples. (3038bc6) * Create API doc in 'dist' target. (2a1216f) * Remove API doc, will be generated in 'dist' target when needed. (486dbd8) Version 0.5 (2008-12-10) ------------------------ .Additions and changes * Moved comment below 'pragma Elaborate_All' in PCSC.Thin.Reader. (840edfc) - Otherwise, this comment is used as package description. * Fixed CHANGELOG after rebase. (c535fb7) * Added CHANGELOG for version 0.5. (f15b76f) * Enabled almost all warnings (except: 'Hiding'). (4ee4b02) - Warnings are treated as errors now. - Fixed elaboration order problem with SCARD_CTL_CODE function in PCSC.Thin.Reader. * Enabled all validity checks. (7136ae9) * Made code comply with new style checks. (01fdac7) * Enabled almost all style checks (all except 'Check sep. specs'). (7e3250e) - Switched to GPS format of project files. * Replaced all Unchecked_Access with just Access in thin_example. (fd09375) * Changed install destination of ALI files, lib and sources. (d5b0974) * Minor coding style fixes, some suggested by gnatpp. (e1638f7) * Added build_lib dependency to install_lib target in Makefile. (6c180f5) * Added version information to 'Build' section in README. (7f201c3) * Added 'dist' target to Makefile to create dist tarball. (2be60a7) * Updated README file. (ecbd973) - Added notice about PC/SC development files to README. - Simplified URLs in README file (works with asciidoc 8.3.0). * No need to obfuscate the AUTHORS e-mail. (c10a946) * Added another TODO item. (8901130) * Removed TODO comment in pcsc-scard body (status: no problem). (e0f9022) * Added Get_PCI() function to retrieve usable PCI for a given Card. (de07e89) * Removed Send_Pci argument from Transmit() procedure. (6b482f0) - Setting the correct send PCI is handled transparently in the thick binding layer. - If a card uses a protocol we don't know a valid PCI for, a No_PCI_for_Proto exception will be thrown. * Fixed Control() and Transmit() procedure. (2ea910a) - The workaround for "access-to-variable designates constant" was broken because only one byte has been passed on to the thin binding. Fixed this by copying the initial send buffer. * Added thick binding subtype IO_Request of Thin.SCARD_IO_REQUEST. (818c183) - Use this subtype for Recv_Pci argument of Transmit() procedure. * Added 0 initialization of SCARD_IO_REQUEST record type fields. (667fdad) * Corrected usage of pioRecvPci argument for SCardTransmit. (cebb7db) * Updated PCSC/Ada API documentation. (c82cf4d) * Removed TODO item (status: done). (5f5ad7c) * Extended purpose header comment of SCard.Monitor package. (c295c5d) * Moved Current_Context from private spec to Reader_Monitor body. (500796c) - Extended Run() entry of Status_Peeker task with Context_Handle argument. The Reader_Monitor uses this entry to pass on the Current_Context to the Status_Peeker task. * Start reader monitoring task after registering the observer. (2c34e37) * Removed Do_Cancel flag: added separate Stop_Peeker, Stop_Monitor. (154c20f) * Renamed 'Status_Observer' task type to 'Status_Peeker'. (21050b4) - Status_Observer is misleading because the expression 'observer' is already used in a different context. * Added more output to simple observer example. (62e3762) * Added S_Reader_Unavailable to interesting states for observer. (2e7bf9c) * Implemented an observer pattern for the Reader_Monitor task. (fb04123) - Client code can extend the abstract type 'Observer' to create new observers. Observers are used to inform the client code about changes in reader state for all known readers. - Observers provide a 'States' Reader_States_Set which stores all the reader states a specific observer is interested in. - Added protected type Protected_Observer_Set as storage for all registered observers. - Added Register() entry to Reader_Monitor, used to add new observers to the protected type Protected_Observer_Set. - Protected_Observer_Set.Notify_All() is used to inform interested observers about a change of reader state. - Added simple reader observer in examples/cardd. * Added missing rgReaderStates argument to SCardGetStatusChange. (eba80ef) - Only needed because adabrowse does not like 'null' default initialization of anonymous access types, see commit 70391cad3b813f5ebfa90f13e47276652fab12fe. * Updated PCSC/Ada API documentation. (8231def) * Removed 'null' initialization of rgReaderStates anonymous access. (e693dde) - adabrowse exits with the error 'null cannot be of an anonymous access type'. * Changed e-mail address for copyright headers. (263e47a) * Ignore non existing pcsc-version.ads file in distclean target. (ab4eac4) * Added exception block around call to Establish_Context(). (d9d7efa) * Added another TODO item. (ac9c1b4) * Made Status_Observer a task type and moved it to private part. (03a0a9b) * Added Status_Observer task to Reader_Monitor task. (50276fe) - Status_Observer calls the Status_Change procedure to detect status changes on all known readers (until Do_Cancel = True). - Renamed Reader_Monitor.Run to Reader_Monitor.Start. - Renamed Reader_Monitor.Cancel to Reader_Monitor.Stop. - Reader_Monitor.Stop does actually stop the Reader_Monitor. * Changed AUTHORS e-mail address. (3104e2a) * Moved Create_Condition and Update_Reader_Table to private part. (e52088c) * Added Cancel() entry to Reader_Monitor task. (44b4cb2) - Renamed Start() to Init(). - Added Run() entry to Reader_Monitor. * Fixed erroneous usage of Reader_Monitor.Run() entry. (c573aac) - Added access to Context type: Context_Handle. - Renamed Run() entry to Start(). - Use the Start rendevous point to init the tasks Current_Context. * Minor: coding style fixes. (58d55ed) * Added missing header comment for Update_Reader_Condition. (8e6766d) * Added missing header comment for Update_Status_Set. (35a8143) * Added missing header for Update_Reader_Table, Create_Condition. (38bcd2e) * Corrected comment for Remove() procedure. (12cadaa) * Fixed handling of 'all reader vanished' event (again). (428e7bc) * Added missing call to Reader_Monitor.Run (Context). (f9866fd) * Re-added exception block in cardd example. (83ac252) * Minor coding style changes. (0271be1) * Replaced Run() procedure of SCard.Monitor with task type. (cb39c8e) * Added handling of empty condition tables to Status_Change(). (8c282ba) * Implemented Event_Counter for Status_Change operation. (9c4e1ce) - SCardGetStatusChange adds an event counter in the upper word of dwEventState. This value must be stored to construct the correct value of dwCurentState for further calls to Status_Change. * Removed type definitions from header comments. (acfad62) * Added code to remove vanished readers from the readers table. (bbd48a4) * Fixed Bug in Update_Status_Set: use correct Index for Event_State. (2ee94d8) * Added support for multiple reader monitoring to SCard.Monitor. (4b90ac6) - Not yet functional. * Added Cancel() procedure to thick binding for Thin.SCardCancel. (17bd157) * Added thin binding for SCardCancel function. (1c7176d) * Fixed problem with Status_Change() and multiple readers. (8f15151) - Removed one indirection: made READERSTATE_Array an array of READERSTATEs, not access to READERSTATEs. - Added Create_Readerstate() helper function to create new Thin.READERSTATE objects. - Removed Thin.READERSTATE_Access type. - Removed Unchecked_Deallocation for Thin.READERSTATE_Access. * Updated TODO item. (2df04cb) * Remove S_Reader_Changed state before updating Current_State. (6e29fe7) * Added Remove() procedure to Reader_States_Set. (69db08f) * Use new SCard.Monitor package for reader condition detection. (7e3e952) * Added SCard.Monitor package. (079ee1f) - Used to monitor reader status changes. At the moment, the simple procedure Run() inside the package just prints the new reader states to stdout. - This code will be replaced by a task implementation of an observer pattern in the future. Client code can then register new observers to the monitor for different reader states. * Renamed Vector_Of_Status_Package to Vector_Of_Condition_Package. (3249fd8) * Added first (not yet working) version of cardd. (c694543) * Changed Get() for Reader_Condition_Set to return a handle. (303dedf) - This throws a GNAT BUG DETECTED with 4.1.2 20061115 (prerelease) (Debian 4.1.1-22) (i486-pc-linux-gnu) * Added another TODO item. (2f52de3) * Added support for multiple Current_States readerstates. (3ae057f) - Removed corresponding TODO item. - Added further functions for simple Set operations ([First|Last]_Item, [First|Last]_Index). - Renamed some existing Set operations to new naming convention. * Renamed Status_Set related parameter names to 'Conditions'. (4c56394) * Refactoring: renamed 'Reader_Status' to 'Reader_Table'. (e171828) * Refactoring: renamed Reader_Status type to Reader_Condition. (bf0f734) - Removed corresponding TODO item. * Use Is_In function of Card_States_Set to test for card presence. (2b1a9e9) * Added Is_In functions for [Card|Reader]_States_Set. (ac3146d) - Used to test if a given State is present in Set. * Minor: Fixed indentation for TODO entry. (38d4464) * Use new SPE_Init() and SPE_Exec() procedures for SPE operations. (8f966c8) * Divided Supports_SPE() into two procedures: SPE_Init, SPE_Exec. (cd79fe0) - SPE_Init is used to check if a reader supports SPE operation. If it does, the Verify_Ctrl value of the card handle is initialized. - SPE_Exec performs the actual SPE operation by sending the Verify_Ctrl code to the reader using a PC/SC v2.0.2 Part 10 PIN verification data structure. * Added Verify_Ctrl DWORD to Card type. (44e990c) * Added SCard_Not_Supported exception. (aa62731) - Raised if an operation has been requested which is not - supported by the reader or card. * First working version of SPE testcode. (4a6cbd8) - The PIN_VERIFY_STRUCTURE is correctly sent to the card reader. * Added representation clause for PIN_VERIFY_STRUCTURE type. (ddb2556) * Extended Supports_SPE() function with PIN verify testcode. (383389d) - Only used to test SPE operation, will be removed later. * Added PIN_VERIFY_STRUCTURE record type to the thin binding. (875d569) * Display info and return if no readers are found. (1a4962f) * Added FEATURE flags to thin binding. (c188014) * Added missing call to Action_Result() after Card Status request. (cd25bcc) * Added record representation clause for PCSC_TLV_STRUCTURE record. (fa844c9) - Not yet tested. * Get card status first before testing for verify feature. (e0b7d20) - Not yet complete, an Is_In() function for Card_States and Reader_States sets is needed to test for a specific state. * Renamed Reader_Proto, Reader_ATR objects to Card_Proto, Card_ATR. (6e17f5a) * Added outer exception block to pinpad example. (59d2f71) * Updated API documentation. (33087da) * Remove generated pcsc-version.ads file when distcleaning. (d1908b9) * Added Action_Info() and Action_Result() helper functions. (4c46b18) - Used by test and example programs to display information and result of a scard operation. * Cleanup in thin binding example. (d0eabbf) * Added project file for all examples. (56b5b41) * Added first version of a SPE operation example. (5cdb784) * Added Supports_SPE() convenience function to the thick binding. (50f1973) - Can be used to test if a reader supporst SPE (secure PIN entry) operations. - First implementation, not yet complete. * Added CM_IOCTL_GET_FEATURE_REQUEST and PCSC_TLV_STRUCTURE. (a9b91ca) * Declared Send_Buffers as constants. (370f96b) * Added SCARD_CTL_CODE function to thin binding. (7379bb4) * Made Send_Buffer of Transmit() and Control() an 'in' parameter. (de8aae7) - Set default value to Null_Byte_Set. - Added access type Byte_Access to thin binding. * Minor: corrected indentation of comments in scard spec file. (77fdafe) * Minor: corrected indentation for procedure params. (9932dea) * Added MAX_BUFFER_SIZE constant to thin binding spec. (f7072af) * Allow Get_Attribute tests to fail. (ac95f24) - Using an explicit exception handler block. - SCardGetAttribute is not supported by all ifd handlers. * Allow READERSTATE_Access to point to the storage pool only. (f5626a7) * Removed valgrind SCardControl related TODO item. (a080370) - "Syscall param write(buf) points to uninitialised byte(s)" also happens when using the C API directly. * Use GNAT external reference in lib project file to set Version. (902466c) * Generate PCSC/Ada version information in Makefile. (44840b2) - Added .gitignore to ignore generated file (pcsc-version.ads) and pcscada.specs (needed for adabrowse). * Added another missing constant keyword in tests_utils body. (55ceabd) * Removed obsolete TODO item (already resolved). (b875c80) * Don't indent package index when generating API doc. (a1e4b67) * Switched to AdaBrowse for automatic API doc generation. (fd28ae4) - Added Makefile target 'docs' to create/update documentation. - Minor specs reformatting to let the generated doc look nicer. * Added "-gnaty3abefhiklmprt" and "-gnatwa" to Compiler switches. (0826eb1) - Fixed various warnings reported by the compiler using these switches (mostly added constant keyword where usable). * Added testcase for Thin.DWORD to Reader_States_Set conversion. (f4cdc9f) * Added testcase for Thin.DWORD to Card_States_Set conversion. (66fdf28) * Added test for Thin.DWORD to type Proto conversion. (f68030d) * Moved Free() for Thin.READERSTATE_Array to Conversion package. (07bdbb8) - Call this function after Test_To_C_RStatus_Set testcase to free memory after test. * Renamed To_LPSTR function to To_Chars_Ptr. (0f5b7d2) - Added corresponding testcase Test_To_Chars_Ptr. * Implemented To_C (Reader_Status_Set) testcase. (d560c9d) * Added To_Reader_ID from String type helper function. (ef24449) * Reduced MAX_ATR_SIZE constant to 32. (0a6be2c) * Added testcase stub for Test_To_C_RStatus_Set. (ece110a) - Tests To_C conversion of Reader_Status_Set type. - Simple function re-ordering in scard-conversion body. * Create position-independent code (PIC) when compiling libpcscada. (5426194) - Store call stack in exceptions for all build targets (utests, itests and lib). * Added first testcase for PCSC.SCard.Conversion package. (cc2d3b3) - Testcase : Slice_Readerstring. - Added Last() and Get() functions for Reader_ID_Set. - Renamed Get_Status() to Get() for Reader_Status_Set. * Added PCSC.SCard.Conversion package description in spec file. (fe2d0b9) * Moved conversion helpers into private package SCard.Conversion. (5026465) - Needed to make these functions/procedures testable. * Removed unneeded 'with Interfaces.C' from utils package. (9d09dd3) * Synced TODO and README files with online versions. (1fab774) * Added another TODO item. (51ed4c4) * Removed Empty_Vector declarations in pcsc-scard package. (86d3034) - Vectors are default initialized to Empty_Vector if not otherwise initialized. - Removed corresponding TODO item. * Using 'Length attribute to test for empty strings in test_utils. (7567067) - Removed corresponding TODO item. * Corrected typo in test_utils package. (1c1e90e) * Use 'private with' for Interfaces.C* in pcsc-scard spec. (a0cd46e) - This guarantees that types declared in these packages are only used in the private part of the thick binding. * Removed Byte_Array_Access related Unchecked_Access attributes. (d80b8a0) - When using anonymous 'access Byte', specifying 'Access works. * Removed declaration of Byte_Array_Access type. (c915892) - Use anonymous 'access Byte' instead. * Completed unit tests for utils package. (06b74e8) - Added Test_BArray_To_Hex_String testcase (tests Byte_Array to hex string conversion). - Declared all Null_* constants in thin binding as private. - Moved declaration of Null_Byte to thin binding; this type is also used in thick binding now. - Added Null_Byte_Array type in pcsc-thin spec. * Added Test_BSet_To_Hex_String testcase. (e0eced7) - Tests Byte_Set to hex string conversion. - Fixed some comments in pcsc-scard-utils spec. - Fixed bug in To_Hex_String (Byte_Set) : o use Length attribute instead of Last attribute. * Minor updates of spec comments. (91f936e) * Added routine stubs for Byte_[Array|Set] to hex string testcases. (6905e23) * Added Null_Byte_Set conversion test to Test_To_Long_Long_Integer. (9fb812b) - Fixed procedure header comment. * Added Test_ATR_To_Hex_String testcase. (8ccb520) - Implemented To_Atr helper function which is used to create new ATR objects from Byte_Sets. - Renamed exception 'Number_Too_Big' to 'Bytes_Too_Big' and moved the spec into pcsc.ads file. * Changed test_pcscada to work with new reader status codes. (9e15223) * Added another TODO item. (8f2bd36) * Added Test_ReaderID_To_String testcase. (9726996) - Made Reader_ID a private type. * Completed Test_CStates_Set_To_String testcase. (e1422c2) - Renamed all card states to start with S_Card_* - Renamed all reader states to start with S_Reader_* - Added procedure to add Card_State to Card_States_Set. o used mainly for testing purposes. * Minor style fixes: indent and exception comment. (e15bf1c) * Added another TODO item. (0dd3d94) * Added empty Reader_States_Set test to Test_RStates_Set_To_String. (7d9b704) * Added stub for Test_CStates_Set_To_String testcase. (452b7ab) * Renamed Convert_Long_Long_Integer to Test_To_Long_Long_Integer. (28e958a) * Removed 'use' clause where appropriate. (ac07e94) - Replaced by 'use type' when operator is needed. * Added test for Reader_States_Set to String conversion. (c28dae3) - Added Add (Reader_State) procedure to make testing possible. - Renamed Add_Reader for Reader_Status type to Add. - Added another TODO item (reduction of 'use clause'). - Use 'box' <> for default values in qualified expressions. * Added another TODO item. (b11775e) - Plus cleanup. - Use capital letters. * Added test for Byte_Set to String conversion. (a386a9f) * Minor style corrections. (0f84756) * Use different obj subdirs for each specific target. (1c7dedb) - Avoids double definitions when linking. * Completed implementation of To_Long_Long_Integer function. (575138d) - Added testcases for a small Byte_Set and a Byte_Set which is too big to be converted to Long_Long_Integer. * Added Number_Too_Big exception. (80edc70) - Will be raised by To_Long_Long_Integer function if a given Byte_Set cannot be converted because it's bigger than Long_Long_Integer'Last. * Replaced To_Integer (Byte_Set) with To_Long_Long_Integer function. (63b0088) - To_Integer worked onyl for Byte_Set (1 .. 2). - To_Long_Long_Integer is not quite ready yet, it cannot handle different Byte_Set sizes. - Added testcase for To_Long_Long_Integer conversion. * Let dummy utils testcase fail (not yet implemented). (b7b9c40) * Added unit test runner (ahven based). (3714855) - Divided pcscada project files into pcscada_lib, pcscada_utests and pcscada_itests. - Added skeleton utils test case. * Create libpcscada.so symlink directly in $(PREFIX)/lib dir. (8886391) * Renamed thick_tests.adb to test_pcscada.adb. (073b15e) - Added utests and itests targets to Makefile. - utests: unit tests (soon to come). - itests: integration tests with reader and smarcard. * Moved thin_tests.adb to new examples directory. (df267ce) * Added install target to Makefile and gnat dynamic library project (bf19223) file. * Initial release version will be '0.5'. (f427f87) * Corrected comment for version constant. (3d48266) * No need for Card_States_Set and Reader_States_Set to be tagged (7b75743) types. * Changed order of Context and Card parameter in Connect procedure. (63b3c58) * Using Update_Status_Set and Update_Reader_Status procedures to update (1386b3c) Reader_Status_Set vector after calling Thin.SCardGetStatusChange. * Added another TODO. (a1250f3) * Added Print_Testinfo and Print_Result helper procedures to display infos about (9533458) running tests. * Added thick binding for SCardControl function. (c2a477c) - Changed send and receive buffer types from void pointers to Byte_Array_Access in thin binding. * Added another TODO item. (7037444) * Removed 'with PCSC.Thin' from thick binding test (not needed any more). (78f6879) * Added Null_[Byte_Set|ATR] default parameters where appropriate. (c0f8541) * Added SCard.Attr_Maxinput Get_Attribute test. (34ea133) - Added To_Integer conversion for Byte_Set. * Refactoring: Use To_Hex_String functions to get hex-representation strings. (9a259bf) - Added another Get_Attribute test case: Attr_ATR_String tag. * Refactoring: Use To_Hex_String functions to get hex-representation strings. (f27e9ff) * Renamed To_String functions to 'To_Hex_String' for those returning (8dd04da) hex-representation strings. - Removed SCard prefix usage in utils package (not needed there). - Added another To_Hex_String function (Byte_Set, implicit length). - Added missing in keywords for function parameters. * Added two more TODOs. (b88a3c2) * Added mapping array for attribute tags. (b8a8991) * Added remaining attribute tags. (fcd9f86) * Left trim Attr_Vendor_Name size output. (5f50b48) * Added more abstraction to Byte_Set type. (d0a5c51) * Extended Init_Attribute_Set function documentation. (527bb40) * Removed Get_Attribute_Size test from thick binding test program. (7a78c64) * Updated package description for PCSC.Thin.Reader. (71cd81b) * Corrected Init_Attribute_Set header comment. (846a413) * Added missing pcsc-thin-reader.ads file. (7c8046b) * Replaced Get_Attribute_Size with Init_Attribute_Set function. (5ccb033) - Returns a Null_Byte initialized byte set which can store the attribute identified by Attr parameter. * First working version of Attribute handling in thick binding code. (c328358) - Added Get_Attribute procedure; used to get attributes from the IFD handler. - Added Get_Attribute_Size function to acquire size needed to store an attribute. - Added tests to thick binding test program. * Added default mode Share_Shared to Connect procedure. (2694d56) * Added more TODOs (preferred proto support for Connect procedure). (04a080c) * Validate Context first before calling Release_Context in (63fb3d2) exception handler code. * Use Return_Code'Image for Image of Return_Code not Thin.DWORD. (cc9d23f) * Rewrote thick binding test program. (df27c42) - It's similar to pcsc-lite testpcsc.c. - This way it's easier to compare the test results. * Last return code from the API is stored by calling Store_Error procedure. (d4ba371) - Get_Return_Code can be used by the client to inquire the last return code. * Print ATR info string after Status_Change test. (e26a015) * Added Size functions for SCard.ATR type. (5bccf9d) * Removed Timeout parameter from Wait_For_Readers procedure. (c0f9af1) * Minor cleanup of declarations in thick_tests body. (7c33b53) * Added Wait_For_Readers procedure. (c729605) - Calls SCardGetStatusChange for reader for detection. - Added Empty_Reader_Status_Set constant. - Waiting for readers to become active works in thick_tests. * Moved Callback type to utils package. (3fc8c40) * Minor style fixes. (925c999) * Minor style correction: use correct indent for function params. (8f442a7) * Replaced Readers_List with private type Reader_ID_Set. (b6dc4d0) - Added functions First and Empty for Reader_ID_Set handling (more to come). - Added Null_Reader_ID constant. - Moved Slice_Readerstring spec to body. * SCard.ATR is a private type now. (15c7a88) - Users do not need to care about ATR length any more. * Added very basic error handling to thin_tests. (3a4142b) * Refactoring: renamed Reader_Status_Array to Reader_Status_Set. (2724e01) - Still not optimal: could be easily confused with Reader_States_Set. * Refactoring: renamed Reader_States_Array to Reader_States_Set. (13002d4) * Refactoring: renamed Card_States_Array to Card_States_Set. (ab0715f) * Free() READERSTATE_Array after converting results back to Ada types. (60a4ef9) * Basic status change detection works for client code. (316ef81) - Added simple Size/Get_Status functions for Reader_Status_Array. - Updating Reader_Status items in Reader_Status_Array by calling Replace_Element. - TODO: Update already existing elements, replacing is not appropriate. * Added explanation to Status_Change procedure. (06d6be2) - Minor refactoring: renamed States to Reader_States. * Implemented To_Ada conversion from C readerstate (DWORD) to Reader_States type. (c41ba87) - Also added To_String function for Reader_States type. * Added type Reader_States_Array. (b87285e) - Used to handle multiple reader states. * Refactoring: renamed Readerstates type to Reader_Status_Array. (6f6cf76) * Refactoring: renamed Card_States to Card_States_Array. (316cdb9) * Use Thin.SCARD_STATE_UNAWARE instead of 0 for dwEventState when constructing C (f871645) states. * Readerstates_Access not needed at the moment. (b939b9c) * Thick binding reader status change detection works. (4ff36ae) - Reduced p2p array to just array of pointers. - Moved spec for thick binding conversion functions to body. - Added some comments. * First version with a thick binding for reader status change detection. (df8f9a1) - Still needs huge cleanup / improvement. - Comments missing. * Removed test status change detection. (2bb614c) - Code did only work for one reader anyway. * Use correct range for Return_Code subtype. (17e7a69) * Updated comments to make API doc look nice. (775fbe4) * Added Byte_Set subtype to thick-binding. (ca9222f) - At the moment, Byte_Sets are just subtypes of Thin.Byte_Arrays; this should be improved by a real abstraction soon. * Minor corrections in comments. (a66e3cd) * Added thick-binding abstraction for SCARD_IO_REQUESTs of thin-binding. (48ad8bd) * Added 'tests' target to Makefile. (17de321) - Used to start thin- and thick-test binaries. * Separated thick- and thin-binding tests into different files. (c1e9cbb) * Added Recv_Len argument to Transmit() procedure. (9f7e245) - Indicates actual bytes returned from SCard. * Use correct value for cbSendLength parameter in Transmit(). (ebd57c0) * Print out test APDU to send before calling Transmit() procedure. (44a0b64) * First basic thick binding implementation of Transmit() procedure. (a533a23) - Needs further abstraction from thin binding. * Moved Print_ReaderID() helper procedure to SCard.Utils package. (dcd13dc) - No need for using Unrestricted_Access in For_Every_Reader() any more. * Card states are handled in an indefinite vector. (9199b58) - Actual implementation is hidden for a client. - Made Utils a child package of PCSC.SCard to provide access to private card states package. * Added Card_State_Array type. (06c27f2) - Stores multiple card states translated from C dword (by To_Ada). - Added To_String for Card_State_Array. * Using correct state type for Status procedure (Card_State). (584dd69) - Bitwise 'and' works. - Renamed some state constants. * Added thick binding for SCardStatus function. (bc17b48) - Prototype, not yet fully functional. Still needs some refactoring. - To_Ada (SCard_State) does not work yet since more than one state is encoded in dwState returned from SCardStatus. * Added thick binding for SCardDisconnect function. (3f63e14) * Added thick binding for SCardEndTransaction function. (ba3612a) - Code cleanup in runner. - Renamed SCard_Init to SCard_Action. * Added thick binding for SCardBeginTransaction function. (bbe58a3) - Removed SCARD_PROTOCOL_T15 proto in Connect and Reconnect procedures for now. * Added thick binding for SCardReconnect procedure. (4e3040a) * Removed SCard_Mode as parameter from Connect procedure in thick binding. (ae22837) - Modes are tried in order. * Moved helper functions/procedures to extra package PCSC.Utils. (82d907d) * Removed Ada.Text_IO, not needed in thick binding. (014876e) * Implemented Get_Active_Proto function. (174d3a3) - Returns protocol in use after SCard connect. * Implemented first working Connect procedure in thick binding. (ae4668e) * Added SCard_Proto type needed for Connect(). (38a529b) - Contains possible SCard protocols. * Added SCard_Mode type needed for Connect(). (03994c7) * For_Every_Reader rewrite. (3c523e3) - Use access to procedure instead of generic. - Print_ReaderID should be moved to new helper scard package. * Added For_Every_Reader generic. (8171b9e) - Can be used to perform actions on all available readers. * Implemented To_String for Reader_ID. (5989b62) * List_Readers returns a vector of Reader_IDs instead of just a string. (8fa9911) - Slice_Readerstring () is responsible for slicing the char array coming from the thin binding into reader friendly names and fill Readers_List vector. - TODO: Implement iterator. * Using aliased char_array for call to SCardListReaders. (2fcf5c0) - No Free () for char_array needed any longer. * List_Readers slices '\0' separated readers list correctly. (2d12659) - Using char_array. - Implemented Free() for char_array. * Fixed memory allocation in ListReaders. (494772c) * Added first thick-binding procedures. (1b3fca9) * Initial import of PCSC/Ada project. (c49ec49) libpcscada-0.7.1/README0000644000175000017500000001025611664137641013161 0ustar reetreetPCSC/Ada README =============== This is the README file for the PCSC/Ada library. In this file, you'll find information on how to compile, test, install the PCSC/Ada library and use the example applications. For the latest information to PCSC/Ada, visit the website at http://www.codelabs.ch/pcscada. Download -------- Release version ~~~~~~~~~~~~~~~ The current release version of PCSC/Ada is available at http://www.codelabs.ch/download. The API documentation of the current release can be found at http://www.codelabs.ch/pcscada/api. Verify a Release ~~~~~~~~~~~~~~~~ To verify the integrity and authenticity of the distribution tarball, import the key http://www.codelabs.ch/keys/0x3DC359DEpub.asc and type the following command: $ gpg --verify libpcscada-{version}.tar.bz2.sig The key fingerprint of the public key ('0x3DC359DE') is: Key fingerprint = 752C 4EBC 115D 5EAD 75F7 0F34 A0AE 8AD7 3DC3 59DE Development version ~~~~~~~~~~~~~~~~~~~ The current development version of PCSC/Ada is available through its git repository http://git.codelabs.ch/git/pcscada.git. A browsable version of the repository is also available here: http://git.codelabs.ch/?p=pcscada.git Build PCSC/Ada -------------- To compile PCSC/Ada on your system, you need the following libraries/frameworks installed: * GNAT (version >= 4.1): http://www.gnu.org/software/gnat/gnat.html * Ahven (Test-Framework, version >= 1.3): http://ahven.stronglytyped.org/ * PC/SC development files and libraries: e.g. pcsc-lite from http://pcsclite.alioth.debian.org (version >= 1.4.0) The build process of PCSC/Ada is quite easy and straightforward. Just type in the following commands: $ tar xjf libpcscada-{revision}.tar.bz2 $ cd libpcscada-{revision} $ make If no errors occur during the build process, you have now successfully built the PCSC/Ada library from sources. Testing ------- Before you install PCSC/Ada on your system, you might want to test the library and verify that everything works as expected. PCSC/Ada contains both a unit test suite and an integration test application. To run the unit tests of PCSC/Ada, just type: $ make utests This will run all Ahven based unit tests. All tests should be marked with *PASS* behind the test name. To run the integration tests of PCSC/Ada, you need to have at least one smart card reader and one smart card ready. Type the following command to run the integration tests: $ make itests This will run an Ada implementation of the pcsc-lite `testpcsc` binary used to test the pcsc-lite framework. If no exception arises, you should be good to go. If you really want make sure everything is alright, compare the output of `make itests` with the output when running `testpcsc` for a given card / reader combination. Installation ------------ To install PCSC/Ada on your system, type the following: $ make PREFIX=/usr/local install You must be `root` to install the library system wide. If no `PREFIX` is specified, `$(HOME)/libraries` is used as install destination. Examples -------- PCSC/Ada provides some example code to demonstrate the usage of the PCSC/Ada API. To build all example apps, type the following: $ make examples You can start an example application like so: `obj/examples/pinpad` examples/cardd ~~~~~~~~~~~~~~ This example application is a simple implementation of a reader monitor using the `Reader_Monitor` task provided by PCSC/Ada. After startup, `cardd` will observe all smart card readers of a system for status changes (e.g. card inserted, card removed). It will print out information if states of readers change. examples/pinvery/pinpad ~~~~~~~~~~~~~~~~~~~~~~~ This small application will perform a SPE (secure pin entry) operation with a given card / reader. It will first check if the reader supports this operation and will exit if not. If it does support SPE, the user is asked to enter the PIN of a given smart card by using the pinpad of the smart card reader. The result of the operation is displayed after completion. examples/thin ~~~~~~~~~~~~~ The thin_example binary (`obj/examples/thin_example`) can be used to test the thin binding of PCSC/Ada. You need to adopt the reader name `Reader_Name` in `examples/thin/thin_example.adb` to make this test app work. libpcscada-0.7.1/pcscada_utests.gpr0000644000175000017500000000233111664137641016013 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with "ahven"; with "pcscada_common"; project PCSCAda_UTests is for Object_Dir use "obj/utests"; for Source_Dirs use ("src", "tests"); for Main use ("runner.adb"); package Compiler is for Default_Switches ("ada") use PCSCAda_Common.Compiler_Switches; end Compiler; package Binder is for Default_Switches ("ada") use ("-E"); end Binder; end PCSCAda_UTests; libpcscada-0.7.1/pcscada_lib.gpr0000644000175000017500000000261111664137641015233 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with "pcscada_common"; project PCSCAda_Lib is for Source_Dirs use ("src"); for Object_Dir use "obj/lib"; for Library_Name use "pcscada"; for Library_Dir use "lib"; for Library_Kind use external ("LIBRARY_KIND", "dynamic"); for Library_Version use "libpcscada.so." & PCSCAda_Common.Version; for Library_Options use ("-lpcsclite"); package Compiler is for Default_Switches ("ada") use PCSCAda_Common.Compiler_Switches; end Compiler; package Binder is for Default_Switches ("ada") use ("-E"); end Binder; end PCSCAda_Lib; libpcscada-0.7.1/pcscada_itests.gpr0000644000175000017500000000232111664137641015776 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with "pcscada_common"; project PCSCAda_ITests is for Object_Dir use "obj/itests"; for Source_Dirs use ("src", "tests"); for Main use ("test_pcscada.adb"); package Compiler is for Default_Switches ("ada") use PCSCAda_Common.Compiler_Switches; end Compiler; package Binder is for Default_Switches ("ada") use ("-E"); end Binder; end PCSCAda_ITests; libpcscada-0.7.1/pcscada_common.gpr0000644000175000017500000000242611664137641015761 0ustar reetreet-- -- Copyright (c) 2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- project PCSCAda_Common is for Source_Dirs use (); for Languages use ("Ada"); Version := external ("PCSCADA_VERSION", "0.1"); Compiler_Switches := ("-gnatygAdISuxo", "-gnatVa", "-gnat05", "-gnatwal", "-gnatf", "-fstack-check", "-gnato", "-g"); end PCSCAda_Common; libpcscada-0.7.1/src/0000755000175000017500000000000011664137641013064 5ustar reetreetlibpcscada-0.7.1/src/pcsc.ads0000644000175000017500000000332411664137641014507 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- This library provides bindings to PC/SC-middleware for the Ada -- programming language. The library allows you to communicate with smart -- cards using the SCard API with Ada. -- -- package PCSC is SCard_Error : exception; -- Raised by all PCSC.SCard routines in case of PC/SC SCard errors. SCard_Not_Supported : exception; -- Raised if an operation has been requested which is not supported by -- the reader or card. Bytes_Too_Big : exception; -- Exception will be raised by utils and helper functions/procedures if a -- given SCard.Byte_Set cannot be converted to a specific type because it -- contains more bytes than the target type can store. No_PCI_for_Proto : exception; -- Exception will be raised if the card uses a protocol we don't know a -- valid PCI (protocol control information) for. end PCSC; libpcscada-0.7.1/src/pcsc-scard-utils.ads0000644000175000017500000001073111664137641016737 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- SCard utilities package. This package contains convenience functions and -- procedures which can be invoked from the client code for specific -- conversion or callback operations. -- -- with PCSC.Thin; with PCSC.SCard; use PCSC; package PCSC.SCard.Utils is type Callback is access procedure (ID : Reader_ID := Null_Reader_ID); -- Callback for reader ID handling. Provides a flexible way to access -- specific readers inside a reader ID set. procedure Action_Info (Text : String); -- This function is used by all test and example programs of PCSC/Ada: -- Pretty print some information about an operation to stdout. After the -- action is complete, the Action_Result() function can be used to display -- the result code of the operation. procedure Action_Result (Result : String); -- Pretty print the result code of an operation to stdout. Before calling -- this function, Action_Info() should be used to describe the operation. procedure For_Every_Reader (Readers : Reader_ID_Set; Call : Callback); -- Call 'Callback' procedure for every reader in readers list. procedure Print_ReaderID (ID : Reader_ID); -- Print out specific reader ID to default output. function To_Hex_String (Given : Byte_Set := Null_Byte_Set; Len : Positive) return String; -- Returns hex-representation string of binary data (Byte_Set). Len defines -- the length of the returned string, this is usally two times the length -- of the initial byte set (because each byte is represented by two -- 'chars'). function To_Hex_String (Given : Byte_Set := Null_Byte_Set) return String; -- Returns hex-representation string of binary data (Byte_Set). The string -- length will be the double length of the initial byte set. If a -- Null_Byte_Set is passed to this function, "0" is returned. function To_Hex_String (Given : Thin.Byte_Array := Thin.Null_Byte_Array; Len : Positive) return String; -- Returns hex-representation string of binary data (Byte_Array). Len -- defines the length of the returned string. function To_Hex_String (Given : ATR := Null_ATR) return String; -- Returns hex-representation string of an ATR. If a Null_ATR is passed, -- "0" is returned. function To_Long_Long_Integer (Given : Byte_Set := Null_Byte_Set) return Long_Long_Integer; -- Return converted Long_Long_Integer value from Byte_Set. Maximal value -- which can be converted is Long_Long_Integer'Last. If given Byte_Set -- contains a bigger number than Long_Long_Integer'Last, a "Number_Too_Big" -- exception will be raised. If a Null_Byte_Set is passed, 0 is returned. function To_String (Reader : Reader_ID := Null_Reader_ID) return String; -- Return string from reader ID. function To_String (States : Card_States_Set) return String; -- Return string representation of card states. function To_String (States : Reader_States_Set) return String; -- Return string representation of reader states. function To_String (Given : Byte_Set := Null_Byte_Set) return String; -- Convert byte set to string. This function does not remove or trim -- newlines. If Null_Byte_Set is passed for 'Given', a "0" string is -- returned. function To_String (Given : Byte_Set := Null_Byte_Set; Len : Natural) return String; -- Convert Len bytes from byte set to string. This function does not remove -- or trim newlines. If Null_Byte_Set is passed for 'Given', a "0" string -- is returned. If Len > Given'Last, Len = Given'Last will be used instead. end PCSC.SCard.Utils; libpcscada-0.7.1/src/pcsc-scard-utils.adb0000644000175000017500000001667111664137641016727 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with Ada.Strings.Unbounded; with Ada.Strings.Fixed; with Interfaces; package body PCSC.SCard.Utils is ------------------------------------------------------------------------- procedure Action_Info (Text : String) is begin Ada.Text_IO.Put (Item => Text); Ada.Text_IO.Set_Col (To => 28); Ada.Text_IO.Put (":"); end Action_Info; ------------------------------------------------------------------------- procedure Action_Result (Result : String) is begin Ada.Text_IO.Set_Col (To => 30); Ada.Text_IO.Put_Line (Item => Result); end Action_Result; ------------------------------------------------------------------------- procedure For_Every_Reader (Readers : Reader_ID_Set; Call : Callback) is Position : VOIDP.Cursor := Readers.Data.First; Reader : Reader_ID; begin while VOIDP.Has_Element (Position) loop Reader := VOIDP.Element (Position); -- Perform action on specific reader. Call (Reader); VOIDP.Next (Position); end loop; end For_Every_Reader; ------------------------------------------------------------------------- procedure Print_ReaderID (ID : Reader_ID) is begin Ada.Text_IO.Put_Line (To_String (ID)); end Print_ReaderID; ------------------------------------------------------------------------- function To_Hex_String (Given : Byte_Set := Null_Byte_Set; Len : Positive) return String is use type Interfaces.Unsigned_8; Hex : constant String := "0123456789ABCDEF"; Result : String (1 .. Len) := (others => '0'); Where : Integer range Result'Range := Result'First; Temp : Interfaces.Unsigned_8; begin if Given = Null_Byte_Set then return "0"; end if; for Index in Given'Range loop Temp := Given (Index); for J in reverse 0 .. 2 - 1 loop Result (Where + J) := Hex (Integer (Temp and 16#F#) + 1); Temp := Interfaces.Shift_Right (Value => Temp, Amount => 4); end loop; if Index /= Given'Last then exit when Where + 2 >= Result'Last; Where := Where + 2; end if; end loop; return Result; end To_Hex_String; ------------------------------------------------------------------------- function To_Hex_String (Given : Byte_Set := Null_Byte_Set) return String is begin if Given = Null_Byte_Set then return "0"; end if; return To_Hex_String (Given => Given, Len => 2 * Given'Length); end To_Hex_String; ------------------------------------------------------------------------- function To_Hex_String (Given : Thin.Byte_Array := Thin.Null_Byte_Array; Len : Positive) return String is use type Thin.Byte_Array; begin if Given = Thin.Null_Byte_Array then return "0"; end if; return To_Hex_String (Given => Byte_Set (Given), Len => Len); end To_Hex_String; ------------------------------------------------------------------------- function To_Hex_String (Given : ATR := Null_ATR) return String is begin if Given = Null_ATR then return "0"; end if; return To_Hex_String (Given => Byte_Set (Given.Data), Len => 2 * Positive (Given.Size)); end To_Hex_String; ------------------------------------------------------------------------- function To_Long_Long_Integer (Given : Byte_Set := Null_Byte_Set) return Long_Long_Integer is use type Interfaces.Unsigned_64; Result, U : Interfaces.Unsigned_64 := 0; begin for Index in Given'Range loop U := Interfaces.Unsigned_64 (Given (Index)); Result := Result or Interfaces.Shift_Left (Value => U, Amount => (Index - 1) * 8); end loop; return Long_Long_Integer (Result); exception when Constraint_Error => raise Bytes_Too_Big; end To_Long_Long_Integer; ------------------------------------------------------------------------- function To_String (Reader : Reader_ID := Null_Reader_ID) return String is begin return Ada.Strings.Unbounded.To_String (Unbounded_String (Reader)); end To_String; ------------------------------------------------------------------------- function To_String (States : Card_States_Set) return String is Str_States : Unbounded_String; Position : VOCSP.Cursor := States.Data.First; State : Card_State; begin while VOCSP.Has_Element (Position) loop State := VOCSP.Element (Position); Str_States := Card_State'Image (State) & " " & Str_States; VOCSP.Next (Position); end loop; -- TODO: find a better solution here! return Ada.Strings.Fixed.Trim (Source => To_String (Str_States), Side => Ada.Strings.Right); end To_String; ------------------------------------------------------------------------- function To_String (States : Reader_States_Set) return String is Str_States : Unbounded_String; Position : VORSP.Cursor := States.Data.First; State : Reader_State; begin while VORSP.Has_Element (Position) loop State := VORSP.Element (Position); Str_States := Reader_State'Image (State) & " " & Str_States; VORSP.Next (Position); end loop; -- TODO: find a better solution here! return Ada.Strings.Fixed.Trim (Source => To_String (Str_States), Side => Ada.Strings.Right); end To_String; ------------------------------------------------------------------------- function To_String (Given : Byte_Set := Null_Byte_Set) return String is begin return To_String (Given => Given, Len => Given'Last); end To_String; ------------------------------------------------------------------------- function To_String (Given : Byte_Set := Null_Byte_Set; Len : Natural) return String is Upper : Natural := Len; begin if Given = Null_Byte_Set then return "0"; end if; if Len > Given'Last then Upper := Given'Last; end if; declare New_String : String (1 .. Upper); begin for Index in Given'First .. Upper loop New_String (Index) := Character'Val (Given (Index)); end loop; return New_String; end; end To_String; end PCSC.SCard.Utils; libpcscada-0.7.1/src/pcsc-scard-conversion.adb0000644000175000017500000001352111664137641017743 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Publ License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Strings.Maps; with Ada.Characters.Latin_1; with GNAT.String_Split; package body PCSC.SCard.Conversion is use Interfaces.C; ------------------------------------------------------------------------- procedure Free (Name : in out Thin.READERSTATE_Array) is begin for Index in Name'Range loop Strings.Free (Name (Index).szReader); end loop; end Free; ------------------------------------------------------------------------- function Slice_Readerstring (To_Slice : String) return Reader_ID_Set is use type GNAT.String_Split.Slice_Number; Readers : Reader_ID_Set; Lines : GNAT.String_Split.Slice_Set; begin -- Slice readers into parts. -- Who uses '\0' as separator anyway? GNAT.String_Split.Create (S => Lines, From => To_Slice (To_Slice'First .. To_Slice'Last), Separators => Ada.Strings.Maps.To_Set (Ada.Characters.Latin_1.NUL), Mode => GNAT.String_Split.Single); -- Minus two because \0\0 is used as termination. for J in 1 .. GNAT.String_Split.Slice_Count (Lines) - 2 loop Readers.Data.Append (New_Item => To_Unbounded_String (GNAT.String_Split.Slice (Lines, J))); end loop; return Readers; end Slice_Readerstring; ------------------------------------------------------------------------- function To_Ada (C_Protocol : Thin.DWORD) return Proto is begin for P in Proto'Range loop if C_Proto (P) = C_Protocol then -- Return active Proto return P; end if; end loop; -- Return 'Undefined' if no active proto found return Proto_Undefined; end To_Ada; ------------------------------------------------------------------------- function To_Ada (C_Cardstate : Thin.DWORD) return Card_States_Set is States : Card_States_Set; begin for P in C_Card_State'Range loop if (C_Cardstate and C_Card_State (P)) /= 0 then States.Data.Append (New_Item => P); end if; end loop; return States; end To_Ada; ------------------------------------------------------------------------- function To_Ada (C_Readerstate : Thin.DWORD) return Reader_States_Set is States : Reader_States_Set; begin for P in C_Reader_State'Range loop if (C_Readerstate and C_Reader_State (P)) /= 0 then States.Data.Append (New_Item => P); end if; end loop; return States; end To_Ada; ------------------------------------------------------------------------- function To_C (Conditions : Reader_Condition_Set) return Thin.READERSTATE_Array is use VORCP; Position : Cursor := Conditions.Data.First; C_States : Thin.READERSTATE_Array (size_t (1) .. size_t (Conditions.Data.Last_Index)); function Create_Readerstate (Condition : Reader_Condition; State : Thin.DWORD) return Thin.READERSTATE; -- Helper function to create a new Thin.READERSTATE object from -- Reader_Condition function Create_Readerstate (Condition : Reader_Condition; State : Thin.DWORD) return Thin.READERSTATE is Current_State : Thin.DWORD := State; Temp : Interfaces.Unsigned_64; begin -- Add event counter in the upper word of dwCurrentState Current_State := State and 16#FFFF#; Temp := Interfaces.Unsigned_64 (Condition.Event_Counter); Current_State := Current_State or Thin.DWORD (Interfaces.Shift_Left (Value => Temp, Amount => 16)); return Thin.READERSTATE' (szReader => Strings.New_String (To_String (Condition.Name)), dwCurrentState => Current_State, cbAtr => Condition.Card_ATR.Data'Length, rgbAtr => Thin.Byte_Array (Condition.Card_ATR.Data), others => <>); end Create_Readerstate; begin while Has_Element (Position) loop declare Item : constant Reader_Condition := Element (Position); C_RState : Thin.DWORD := 0; begin for S in Natural range Item.Current_State.First_Index .. Item.Current_State.Last_Index loop C_RState := C_RState or C_Reader_State (Item.Current_State.Get (Index => S)); end loop; C_States (size_t (To_Index (Position))) := Create_Readerstate (Condition => Item, State => C_RState); Next (Position); end; end loop; return C_States; end To_C; ------------------------------------------------------------------------- function To_Chars_Ptr (Reader : Reader_ID) return Strings.chars_ptr is begin return Strings.New_String (To_String (Reader)); end To_Chars_Ptr; end PCSC.SCard.Conversion; libpcscada-0.7.1/src/pcsc-thin-reader.ads0000644000175000017500000002332211664137641016707 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- This package keeps a list of attributes which can be requested directly -- from the IFD handler. Use the @Init_Attribute_Set@ and @Get_Attribute@ -- functions to do so. It also provides the constants and types needed for -- feature handling and PIN verification operations. -- -- with PCSC.Thin; pragma Elaborate_All (PCSC.Thin); package PCSC.Thin.Reader is SCARD_ATTR_VENDOR_NAME : constant := 16#0001_0100#; -- Vendor name SCARD_ATTR_VENDOR_IFD_TYPE : constant := 16#0001_0101#; -- Vendor-supplied interface device type (model designation of reader) SCARD_ATTR_VENDOR_IFD_VERSION : constant := 16#0001_0102#; -- Vendor-supplied interface device version (DWORD in the form 0xMMmmbbbb -- where MM = major version, mm = minor version, and bbbb = build number). SCARD_ATTR_VENDOR_IFD_SERIAL_NO : constant := 16#0001_0103#; -- Vendor-supplied interface device serial number SCARD_ATTR_CHANNEL_ID : constant := 16#0002_0110#; -- DWORD encoded as 0xDDDDCCCC, where DDDD = data channel type and CCCC = -- channel number. SCARD_ATTR_DEFAULT_CLK : constant := 16#0003_0121#; -- Default clock rate, in kHz SCARD_ATTR_MAX_CLK : constant := 16#0003_0122#; -- Maximum clock rate, in kHz SCARD_ATTR_DEFAULT_DATA_RATE : constant := 16#0003_0123#; -- Default data rate, in bps SCARD_ATTR_MAX_DATA_RATE : constant := 16#0003_0124#; -- Maximum data rate, in bps SCARD_ATTR_MAX_IFSD : constant := 16#0003_0125#; -- Maximum bytes for information file size device SCARD_ATTR_POWER_MGMT_SUPPORT : constant := 16#0004_0131#; -- Zero if device does not support power down while smart card is inserted. -- Nonzero otherwise. SCARD_ATTR_CHARACTERISTICS : constant := 16#0006_0150#; -- DWORD indicating which mechanical characteristics are supported. If -- zero, no special characteristics are supported. Note that multiple bits -- can be set. SCARD_ATTR_CURRENT_PROTOCOL_TYPE : constant := 16#0008_0201#; -- Current protocol type in use SCARD_ATTR_CURRENT_CLK : constant := 16#0008_0202#; -- Current clock rate, in kHz SCARD_ATTR_CURRENT_F : constant := 16#0008_0203#; -- Clock conversion factor SCARD_ATTR_CURRENT_D : constant := 16#0008_0204#; -- Bit rate conversion factor SCARD_ATTR_CURRENT_N : constant := 16#0008_0205#; -- Current guard time SCARD_ATTR_CURRENT_W : constant := 16#0008_0206#; -- Current work waiting time SCARD_ATTR_CURRENT_IFSC : constant := 16#0008_0207#; -- Current byte size for information field size card SCARD_ATTR_CURRENT_IFSD : constant := 16#0008_0208#; -- Current byte size for information field size device SCARD_ATTR_CURRENT_BWT : constant := 16#0008_0209#; -- Current block waiting time SCARD_ATTR_CURRENT_CWT : constant := 16#0008_020A#; -- Current character waiting time SCARD_ATTR_CURRENT_EBC_ENCODING : constant := 16#0008_020B#; -- Current error block control encoding SCARD_ATTR_EXTENDED_BWT : constant := 16#0008_020C#; -- Extended block waiting time SCARD_ATTR_ICC_PRESENCE : constant := 16#0009_0300#; -- Single byte indicating smart card presence SCARD_ATTR_ICC_INTERFACE_STATUS : constant := 16#0009_0301#; -- Single byte. Zero if smart card electrical contact is not active; -- nonzero if contact is active. SCARD_ATTR_CURRENT_IO_STATE : constant := 16#0009_0302#; SCARD_ATTR_ATR_STRING : constant := 16#0009_0303#; -- Answer to reset (ATR) string SCARD_ATTR_ICC_TYPE_PER_ATR : constant := 16#0009_0304#; -- Single byte indicating smart card type SCARD_ATTR_ESC_RESET : constant := 16#0007_A000#; SCARD_ATTR_ESC_CANCEL : constant := 16#0007_A003#; SCARD_ATTR_ESC_AUTHREQUEST : constant := 16#0007_A005#; SCARD_ATTR_MAXINPUT : constant := 16#0007_A007#; SCARD_ATTR_DEVICE_UNIT : constant := 16#7FFF_0001#; -- Instance of this vendor's reader attached to the computer. The first -- instance will be device unit 0, the next will be unit 1 (if it is the -- same brand of reader) and so on. Two different brands of readers will -- both have zero for this value. SCARD_ATTR_DEVICE_IN_USE : constant := 16#7FFF_0002#; -- Reserved for future use SCARD_ATTR_DEVICE_FRIENDLY_NAME_A : constant := 16#7FFF_0003#; SCARD_ATTR_DEVICE_SYSTEM_NAME_A : constant := 16#7FFF_0004#; SCARD_ATTR_DEVICE_FRIENDLY_NAME_W : constant := 16#7FFF_0005#; SCARD_ATTR_DEVICE_SYSTEM_NAME_W : constant := 16#7FFF_0006#; SCARD_ATTR_SUPRESS_T1_IFS_REQUEST : constant := 16#7FFF_0007#; CM_IOCTL_GET_FEATURE_REQUEST : constant DWORD := SCARD_CTL_CODE (3400); -- Control code used to get features from card / reader. FEATURE_VERIFY_PIN_START : constant := 16#01#; -- OMNIKEY Proposal FEATURE_VERIFY_PIN_FINISH : constant := 16#02#; -- OMNIKEY Proposal FEATURE_MODIFY_PIN_START : constant := 16#03#; -- OMNIKEY Proposal FEATURE_MODIFY_PIN_FINISH : constant := 16#04#; -- OMNIKEY Proposal FEATURE_GET_KEY_PRESSED : constant := 16#05#; -- OMNIKEY Proposal FEATURE_VERIFY_PIN_DIRECT : constant := 16#06#; -- USB CCID PIN Verify FEATURE_MODIFY_PIN_DIRECT : constant := 16#07#; -- USB CCID PIN Modify FEATURE_MCT_READERDIRECT : constant := 16#08#; -- KOBIL Proposal FEATURE_MCT_UNIVERSAL : constant := 16#09#; -- KOBIL Proposal FEATURE_IFD_PIN_PROP : constant := 16#0A#; -- Gemplus Proposal FEATURE_ABORT : constant := 16#0B#; -- SCM Proposal type PCSC_TLV_STRUCTURE is record tag : Interfaces.Unsigned_8; length : Interfaces.Unsigned_8; value : Interfaces.Unsigned_32; -- This value is always in BIG ENDIAN format as documented in PCSC v2 -- part 10 ch 2.2 page 2. end record; -- PCSC Type-length-value data structure for PCSC_TLV_STRUCTURE use record tag at 0 range 0 .. 7; length at 0 range 8 .. 15; value at 0 range 16 .. 47; end record; -- Representation clause for PCSC_TLV_STRUCTURE type for PCSC_TLV_STRUCTURE'Size use 48; -- The PCSC_TLV_STRUCTURE must be exactly 6 bytes long type PIN_VERIFY_STRUCTURE is record bTimerOut : aliased Byte; -- Timeout is seconds (00 means use default timeout) bTimerOut2 : Byte; -- Timeout in seconds after first key stroke bmFormatString : Byte; -- Formatting options bmPINBlockString : Byte; -- Bits 7-4 bit size of PIN length in APDU, bits 3-0 PIN block size in -- bytes after justification and formatting bmPINLengthFormat : Byte; -- Bits 7-5 RFU, bit 4 set if system units are bytes, clear if system -- units are bits, bits 3-0 PIN length position in system units wPINMaxExtraDigit : Interfaces.Unsigned_16; -- 0xXXYY where XX is minimum PIN size in digits, and YY is maximum PIN -- size in digits bEntryValidationCondition : Byte; -- Conditions under which PIN entry should be considered complete bNumberMessage : Byte; -- Number of messages to display for PIN verification wLangId : Interfaces.Unsigned_16; -- Language for messages bMsgIndex : Byte := 0; -- Message index (should be 00) bTeoPrologue : Byte_Array (1 .. 3) := (others => 0); -- T=1 block prologue field to use (filled with 00) ulDataLength : Interfaces.Unsigned_32; -- Length of Data to be sent to the ICC abData : Byte_Array (1 .. MAX_BUFFER_SIZE) := (others => 0); -- Data to send to the ICC end record; for PIN_VERIFY_STRUCTURE use record bTimerOut at 0 range 0 .. 7; bTimerOut2 at 1 range 0 .. 7; bmFormatString at 2 range 0 .. 7; bmPINBlockString at 3 range 0 .. 7; bmPINLengthFormat at 4 range 0 .. 7; wPINMaxExtraDigit at 5 range 0 .. 15; bEntryValidationCondition at 7 range 0 .. 7; bNumberMessage at 8 range 0 .. 7; wLangId at 9 range 0 .. 15; bMsgIndex at 11 range 0 .. 7; bTeoPrologue at 12 range 0 .. 23; ulDataLength at 15 range 0 .. 31; abData at 19 range 0 .. (MAX_BUFFER_SIZE * 8) - 1; end record; -- Representation clause for PIN_VERIFY_STRUCTURE type end PCSC.Thin.Reader; libpcscada-0.7.1/src/pcsc-scard.adb0000644000175000017500000010213311664137641015556 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Publ License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Exceptions; with Ada.Strings.Fixed; with Interfaces.C; with Interfaces.C.Strings; with PCSC.SCard.Conversion; with PCSC.Thin.Reader; with PCSC.SCard.Utils; package body PCSC.SCard is use Interfaces.C; package Convert renames PCSC.SCard.Conversion; ------------------------------------------------------------------------- procedure Add (States : in out Card_States_Set; State : Card_State) is begin States.Data.Append (New_Item => State); end Add; ------------------------------------------------------------------------- procedure Add (States : in out Reader_States_Set; State : Reader_State) is begin States.Data.Append (New_Item => State); end Add; ------------------------------------------------------------------------- procedure Add (Set : in out Reader_Condition_Set; Status : Reader_Condition) is begin Set.Data.Append (New_Item => Status); end Add; ------------------------------------------------------------------------- procedure Begin_Transaction (Card : SCard.Card) is Res : Thin.DWORD; begin Res := Thin.SCardBeginTransaction (hCard => Card.hCard); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Begin of transaction failed"); end if; Store_Error (Code => Res); end Begin_Transaction; ------------------------------------------------------------------------- procedure Cancel (Context : SCard.Context) is Res : Thin.DWORD; begin Res := Thin.SCardCancel (hContext => Context.hContext); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Cancel operation failed"); end if; Store_Error (Code => Res); end Cancel; ------------------------------------------------------------------------- procedure Connect (Context : SCard.Context; Card : in out SCard.Card; Reader : Reader_ID := Null_Reader_ID; Mode : SCard.Mode := Share_Shared) is Res : Thin.DWORD; C_Reader : Thin.LPSTR := Convert.To_Chars_Ptr (Reader => Reader); begin Res := Thin.SCardConnect (hContext => Context.hContext, szReader => C_Reader, dwShareMode => Convert.C_Mode (Mode), dwPreferredProtocols => Thin.SCARD_PROTOCOL_T1 or Thin.SCARD_PROTOCOL_T0, phCard => Card.hCard'Access, pdwActiveProtocol => Card.Active_Proto'Access); if Res /= Thin.SCARD_S_SUCCESS then Strings.Free (C_Reader); SCard_Exception (Code => Res, Message => "Could not connect to reader"); end if; Store_Error (Code => Res); -- Free allocated memory Strings.Free (C_Reader); end Connect; ------------------------------------------------------------------------- procedure Control (Card : SCard.Card; Code : Natural; Send_Buffer : Byte_Set := Null_Byte_Set; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural) is Res : Thin.DWORD; Sbuffer_Copy : aliased Byte_Set := Send_Buffer; -- Copy of initial Send_Buffer. This is needed because we cannot -- directly pass the 'in' Parameter Send_Buffer as : -- pbSendBuffer => Send_Buffer (Send_Buffer'First)'Access -- to the thin binding. If we try, the compiler complains: -- access-to-variable designates constant Send_First_Ptr : Thin.Byte_Access; -- Pointer to first byte of send buffer Recv_Length : aliased constant Thin.DWORD := Thin.DWORD (Recv_Buffer'Length); Bytes_Returned : aliased Thin.DWORD := 0; begin -- The send buffer can also by empty, replace with null ptr if it is if Send_Buffer = Null_Byte_Set then Send_First_Ptr := null; else Send_First_Ptr := Sbuffer_Copy (Sbuffer_Copy'First)'Unchecked_Access; end if; Res := Thin.SCardControl (hCard => Card.hCard, dwControlCode => Thin.DWORD (Code), pbSendBuffer => Send_First_Ptr, cbSendLength => Thin.DWORD (Send_Buffer'Length), pbRecvBuffer => Recv_Buffer (Recv_Buffer'First)'Access, cbRecvLength => Recv_Length, lpBytesReturned => Bytes_Returned'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Sending Control to Card failed"); end if; Store_Error (Code => Res); -- Return read bytes count Recv_Len := Natural (Bytes_Returned); end Control; ------------------------------------------------------------------------- procedure Disconnect (Card : SCard.Card; Action : SCard.Action) is Res : Thin.DWORD; begin Res := Thin.SCardDisconnect (hCard => Card.hCard, dwDisposition => Convert.C_Action (Action)); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Could not disconnect from reader"); end if; Store_Error (Code => Res); end Disconnect; ------------------------------------------------------------------------- function Empty (Set : Reader_ID_Set) return Boolean is use type Ada.Containers.Count_Type; begin if Set.Data.Length = 0 then return True; end if; return False; end Empty; ------------------------------------------------------------------------- procedure End_Transaction (Card : SCard.Card; Action : SCard.Action) is Res : Thin.DWORD; begin Res := Thin.SCardEndTransaction (hCard => Card.hCard, dwDisposition => Convert.C_Action (Action)); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "End of transaction failed"); end if; Store_Error (Code => Res); end End_Transaction; ------------------------------------------------------------------------- procedure Establish_Context (Context : in out SCard.Context; Scope : SCard.Scope) is Res : Thin.DWORD; begin Res := Thin.SCardEstablishContext (dwScope => Convert.C_Scope (Scope), phContext => Context.hContext'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Context failed"); end if; Store_Error (Code => Res); end Establish_Context; ------------------------------------------------------------------------- function Find (Set : Reader_Condition_Set; Reader_ID : SCard.Reader_ID) return Boolean is Position : VORCP.Cursor := Set.Data.First; Item : Reader_Condition; begin while VORCP.Has_Element (Position) loop Item := VORCP.Element (Position); if Item.Name = Reader_ID then return True; end if; VORCP.Next (Position); end loop; return False; end Find; ------------------------------------------------------------------------- function First_Index (Set : Reader_ID_Set) return Natural is begin return Set.Data.First_Index; end First_Index; ------------------------------------------------------------------------- function First_Index (Set : Reader_States_Set) return Natural is begin return Set.Data.First_Index; end First_Index; ------------------------------------------------------------------------- function First_Index (Set : Reader_Condition_Set) return Natural is begin return Set.Data.First_Index; end First_Index; ------------------------------------------------------------------------- function First_Item (Set : Reader_ID_Set) return Reader_ID is use type Ada.Containers.Count_Type; begin if Set.Data.Length = 0 then return Null_Reader_ID; end if; return Set.Data.First_Element; end First_Item; ------------------------------------------------------------------------- function First_Item (Set : Reader_States_Set) return Reader_State is use type Ada.Containers.Count_Type; begin return Set.Data.First_Element; end First_Item; ------------------------------------------------------------------------- function Get (Set : Reader_ID_Set; Index : Natural) return Reader_ID is begin -- TODO: bound checks on 'Index' return Set.Data.Element (Index); end Get; ------------------------------------------------------------------------- function Get (Set : Reader_States_Set; Index : Natural) return Reader_State is begin -- TODO: bound checks on 'Index' return Set.Data.Element (Index); end Get; ------------------------------------------------------------------------- function Get (Set : Reader_Condition_Set; Index : Natural) return Reader_Condition is begin -- TODO: bound checks on 'Index' return Set.Data.Element (Index); end Get; ------------------------------------------------------------------------- function Get_Active_Proto (Card : SCard.Card) return Proto is begin return Convert.To_Ada (Card.Active_Proto); end Get_Active_Proto; ------------------------------------------------------------------------- procedure Get_Attribute (Card : SCard.Card; Attr : Attribute; Recv_Buffer : in out Byte_Set) is Res : Thin.DWORD; Len : aliased Thin.DWORD := Recv_Buffer'Length; begin Res := Thin.SCardGetAttrib (hCard => Card.hCard, dwAttrId => Convert.C_Attr (Attr), pbAttr => Recv_Buffer (Recv_Buffer'First)'Access, pcbAttrLen => Len'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Get attribute failed"); end if; Store_Error (Code => Res); end Get_Attribute; ------------------------------------------------------------------------- function Get_PCI (Card : SCard.Card) return Thin.SCARD_IO_REQUEST is PCI : Thin.SCARD_IO_REQUEST; begin -- TODO: use a mapping table for this if Card.Active_Proto = Thin.SCARD_PROTOCOL_T0 then PCI := Thin.SCARD_PCI_T0; elsif Card.Active_Proto = Thin.SCARD_PROTOCOL_T1 then PCI := Thin.SCARD_PCI_T1; elsif Card.Active_Proto = Thin.SCARD_PROTOCOL_RAW then PCI := Thin.SCARD_PCI_RAW; else raise No_PCI_for_Proto; end if; return PCI; end Get_PCI; ------------------------------------------------------------------------- function Get_Return_Code return String is Err_Message : constant String := Strings.Value (Thin.pcsc_stringify_error (Last_Return_Code)); begin return Err_Message; end Get_Return_Code; ------------------------------------------------------------------------- function Init_Attribute_Set (Card : SCard.Card; Attr : Attribute) return Byte_Set is Res : Thin.DWORD; Len : aliased Thin.DWORD := 0; begin Res := Thin.SCardGetAttrib (hCard => Card.hCard, dwAttrId => Convert.C_Attr (Attr), pbAttr => null, pcbAttrLen => Len'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Init attribute set failed"); end if; Store_Error (Code => Res); declare B : constant Byte_Set (1 .. Positive (Len)) := (others => Thin.Null_Byte); begin return B; end; end Init_Attribute_Set; ------------------------------------------------------------------------- function Is_In (States : Reader_States_Set; State : Reader_State) return Boolean is use type VORSP.Cursor; begin if States.Data.Find (Item => State) = VORSP.No_Element then return False; end if; return True; end Is_In; ------------------------------------------------------------------------- function Is_In (States : Card_States_Set; State : Card_State) return Boolean is use type VOCSP.Cursor; begin if States.Data.Find (Item => State) = VOCSP.No_Element then return False; end if; return True; end Is_In; ------------------------------------------------------------------------- function Is_Valid (Context : SCard.Context) return Boolean is Res : Thin.DWORD; begin Res := Thin.SCardIsValidContext (hContext => Context.hContext); if Res /= Thin.SCARD_S_SUCCESS then Store_Error (Code => Res); return False; end if; Store_Error (Code => Res); return True; end Is_Valid; ------------------------------------------------------------------------- function Last_Index (Set : Reader_ID_Set) return Natural is begin return Set.Data.Last_Index; end Last_Index; ------------------------------------------------------------------------- function Last_Index (Set : Reader_States_Set) return Natural is begin return Set.Data.Last_Index; end Last_Index; ------------------------------------------------------------------------- function Last_Index (Set : Reader_Condition_Set) return Natural is begin return Set.Data.Last_Index; end Last_Index; ------------------------------------------------------------------------- function Last_Item (Set : Reader_ID_Set) return Reader_ID is use type Ada.Containers.Count_Type; begin if Set.Data.Length = 0 then return Null_Reader_ID; end if; return Set.Data.Last_Element; end Last_Item; ------------------------------------------------------------------------- function Last_Item (Set : Reader_States_Set) return Reader_State is use type Ada.Containers.Count_Type; begin return Set.Data.Last_Element; end Last_Item; ------------------------------------------------------------------------- function Length (Set : Reader_Condition_Set) return Natural is begin return Natural (Set.Data.Length); end Length; ------------------------------------------------------------------------- function List_Readers (Context : SCard.Context) return Reader_ID_Set is Res : Thin.DWORD; Len : aliased Thin.DWORD := 0; begin -- Calculate the space required to store the reader's friendly name. Res := Thin.SCardListReaders (hContext => Context.hContext, mszReaders => Strings.Null_Ptr, pcchReaders => Len'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Could not get readers"); end if; declare C_Readers : aliased char_array := (1 .. size_t (Len) => <>); begin -- Get readers for this context Res := Thin.SCardListReaders (hContext => Context.hContext, mszReaders => Strings.To_Chars_Ptr (C_Readers'Unchecked_Access), pcchReaders => Len'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Could not get readers"); end if; Store_Error (Code => Res); -- Convert to Ada types declare Readers : constant String := To_Ada (Item => C_Readers, Trim_Nul => False); begin return Convert.Slice_Readerstring (To_Slice => Readers); end; end; end List_Readers; ------------------------------------------------------------------------- procedure Reconnect (Card : in out SCard.Card; Mode : SCard.Mode; Action : SCard.Action) is Res : Thin.DWORD; begin Res := Thin.SCardReconnect (hCard => Card.hCard, dwShareMode => Convert.C_Mode (Mode), dwPreferredProtocols => Thin.SCARD_PROTOCOL_T1 or Thin.SCARD_PROTOCOL_T0, dwInitialization => Convert.C_Action (Action), pdwActiveProtocol => Card.Active_Proto'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Could not reconnect to reader"); end if; Store_Error (Code => Res); end Reconnect; ------------------------------------------------------------------------- procedure Release_Context (Context : in out SCard.Context) is Res : Thin.DWORD; begin Res := Thin.SCardReleaseContext (hContext => Context.hContext); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Could not release context"); end if; Store_Error (Code => Res); end Release_Context; ------------------------------------------------------------------------- procedure Remove (States : in out Reader_States_Set; State : Reader_State) is begin -- TODO: error handling when state is not found States.Data.Delete (Index => States.Data.Find_Index (Item => State)); end Remove; ------------------------------------------------------------------------- procedure SCard_Exception (Code : Thin.Return_Code; Message : String) is Err_Message : constant String := Strings.Value (Thin.pcsc_stringify_error (Code)); begin -- Store return code Store_Error (Code => Code); Ada.Exceptions.Raise_Exception (SCard_Error'Identity, Message & " - [" & Thin.Return_Code'Image (Code) & "] " & Err_Message); end SCard_Exception; ------------------------------------------------------------------------- function Size (Atr : SCard.ATR := Null_ATR) return Natural is begin return Natural (Atr.Size); end Size; ------------------------------------------------------------------------- function Size (Atr : SCard.ATR := Null_ATR) return String is Natural_ATR : constant Natural := Size (Atr); begin -- Remove leading space return Ada.Strings.Fixed.Trim (Source => Natural'Image (Natural_ATR), Side => Ada.Strings.Left); end Size; ------------------------------------------------------------------------- procedure SPE_Exec (Card : in out SCard.Card; Result : in out Byte_Set) is package TR renames Thin.Reader; Res : Thin.DWORD; Verify_Struct : TR.PIN_VERIFY_STRUCTURE; Recv_Buffer : Thin.Byte_Array (1 .. Thin.MAX_BUFFER_SIZE); Recv_Len : aliased Thin.DWORD := 0; Supported : Boolean := False; begin -- Check control code of this card if Card.Verify_Ctrl = 0 then SPE_Init (Card => Card, Result => Supported); if not Supported then raise SCard_Not_Supported; end if; end if; -- Construct PC/SC v2.0.2 Part 10 PIN verification data structure Verify_Struct.bTimerOut := 0; Verify_Struct.bTimerOut2 := 0; Verify_Struct.bmFormatString := 16#82#; Verify_Struct.bmPINBlockString := 16#04#; Verify_Struct.bmPINLengthFormat := 0; Verify_Struct.wPINMaxExtraDigit := 16#0408#; Verify_Struct.bEntryValidationCondition := 16#02#; Verify_Struct.bNumberMessage := 16#01#; Verify_Struct.wLangId := 16#0904#; Verify_Struct.bMsgIndex := 0; Verify_Struct.abData (1) := 16#00#; Verify_Struct.abData (2) := 16#20#; Verify_Struct.abData (3) := 16#00#; Verify_Struct.abData (4) := 16#00#; Verify_Struct.abData (5) := 16#08#; Verify_Struct.abData (6) := 16#30#; Verify_Struct.abData (7) := 16#30#; Verify_Struct.abData (8) := 16#30#; Verify_Struct.abData (9) := 16#30#; Verify_Struct.abData (10) := 16#00#; Verify_Struct.abData (11) := 16#00#; Verify_Struct.abData (12) := 16#00#; Verify_Struct.abData (13) := 16#00#; Verify_Struct.ulDataLength := 13; Res := Thin.SCardControl (hCard => Card.hCard, dwControlCode => Card.Verify_Ctrl, pbSendBuffer => Verify_Struct.bTimerOut'Access, cbSendLength => 32, -- Exact size of Verify_Struct object pbRecvBuffer => Recv_Buffer (Recv_Buffer'First)'Access, cbRecvLength => Thin.DWORD (Recv_Buffer'Length), lpBytesReturned => Recv_Len'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Verify control failed"); end if; -- Store Bytes returned from reader in Result byte set -- TODO: this assumes return code to be two bytes. Fix by using a more -- flexible way of Byte_Set size handling (handles to byte sets?) for Index in Result'Range loop Result (Index) := Recv_Buffer (Index); end loop; end SPE_Exec; ------------------------------------------------------------------------- procedure SPE_Init (Card : in out SCard.Card; Result : in out Boolean) is package TR renames Thin.Reader; Res : Thin.DWORD; Recv_Buffer : Thin.Byte_Array (1 .. Thin.MAX_BUFFER_SIZE); Recv_Len : aliased Thin.DWORD := 0; Elements : Natural := 0; begin Result := False; Res := Thin.SCardControl (hCard => Card.hCard, dwControlCode => TR.CM_IOCTL_GET_FEATURE_REQUEST, pbSendBuffer => null, cbSendLength => 0, pbRecvBuffer => Recv_Buffer (Recv_Buffer'First)'Access, cbRecvLength => Thin.DWORD (Recv_Buffer'Length), lpBytesReturned => Recv_Len'Access); if Res /= Thin.SCARD_S_SUCCESS then Store_Error (Code => Res); return; end if; Store_Error (Code => Res); -- Verify the result if Recv_Len mod (TR.PCSC_TLV_STRUCTURE'Size / 8) > 0 then -- Received buffer can not be used, return False return; end if; -- Get number of TLV elements instead of the complete size Elements := Integer (Recv_Len) / (TR.PCSC_TLV_STRUCTURE'Size / 8); -- Create TLV structure from bytes received -- TODO: create a function/procedure to do this job in a more -- effective way. declare use type Interfaces.Unsigned_8; TLV_Array : array (1 .. Elements) of TR.PCSC_TLV_STRUCTURE; T : Natural := Recv_Buffer'First; Index : Natural := TLV_Array'First; Value : Byte_Set (1 .. 4); begin loop exit when T >= Natural (Recv_Len); TLV_Array (Index).tag := Recv_Buffer (T); TLV_Array (Index).length := Recv_Buffer (T + 1); -- Value is stored in Big endian format Value (4) := Recv_Buffer (T + 2); Value (3) := Recv_Buffer (T + 3); Value (2) := Recv_Buffer (T + 4); Value (1) := Recv_Buffer (T + 5); TLV_Array (Index).value := Interfaces.Unsigned_32 (Utils.To_Long_Long_Integer (Given => Value)); T := T + 6; Index := Index + 1; end loop; -- Test for FEATURE_VERIFY_PIN_DIRECT flag for Index in Natural range TLV_Array'Range loop if TLV_Array (Index).tag = TR.FEATURE_VERIFY_PIN_DIRECT then -- Store verify control code for this card Card.Verify_Ctrl := Thin.DWORD (TLV_Array (Index).value); Result := True; return; end if; end loop; end; end SPE_Init; ------------------------------------------------------------------------- procedure Status (Card : SCard.Card; State : out SCard.Card_States_Set; Proto : out SCard.Proto; Atr : out SCard.ATR) is Res : Thin.DWORD; dwReaderLen : aliased Thin.DWORD; dwState : aliased Thin.DWORD; dwProtocol : aliased Thin.DWORD; dwAtrLen : aliased Thin.DWORD := Thin.MAX_ATR_SIZE; begin Thin.SCardStatus (returnValue => Res, hCard => Card.hCard, mszReaderNames => Strings.Null_Ptr, pcchReaderLen => dwReaderLen'Access, pdwState => dwState'Access, pdwProtocol => dwProtocol'Access, pbAtr => Thin.Byte_Array (Atr.Data), pcbAtrLen => dwAtrLen'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Get status failed"); end if; Store_Error (Code => Res); -- Assign in out params Atr.Size := ATR_Byte_Count (dwAtrLen); Proto := Convert.To_Ada (dwProtocol); State := Convert.To_Ada (dwState); end Status; ------------------------------------------------------------------------- procedure Status_Change (Context : SCard.Context; Timeout : Natural := 0; Conditions : in out Reader_Condition_Set) is use type VORCP.Vector; Res : Thin.DWORD; C_Timeout : Thin.DWORD; C_States : Thin.READERSTATE_Array := Convert.To_C (Conditions => Conditions); procedure Update_Status_Set (Position : VORCP.Cursor); -- Update the status set given by cursor. procedure Update_Status_Set (Position : VORCP.Cursor) is procedure Update_Reader_Condition (Element : in out Reader_Condition); -- Update reader condition element. procedure Update_Reader_Condition (Element : in out Reader_Condition) is use type Interfaces.Unsigned_64; Counter : Interfaces.Unsigned_64; ATR_Bytes : constant Thin.DWORD := C_States (size_t (VORCP.To_Index (Position))).cbAtr; begin Element.Event_State := Convert.To_Ada (C_States (size_t (VORCP.To_Index (Position))).dwEventState); if ATR_Bytes > 0 then Element.Card_ATR.Data := ATR_Data_Type (C_States (size_t (VORCP.To_Index (Position))).rgbAtr); Element.Card_ATR.Size := ATR_Byte_Count (ATR_Bytes); else Element.Card_ATR := Null_ATR; end if; -- Update event counter for this condition Counter := Interfaces.Unsigned_64 (C_States (size_t (VORCP.To_Index (Position))).dwEventState); Counter := Interfaces.Shift_Right (Value => Counter, Amount => 16); Counter := Counter and 16#FFFF#; Element.Event_Counter := Natural (Counter); end Update_Reader_Condition; begin Conditions.Data.Update_Element (Position => Position, Process => Update_Reader_Condition'Access); end Update_Status_Set; begin -- Check for empty reader conditions if Conditions.Data = VORCP.Empty_Vector then -- Just wait for readers to appear, then return Wait_For_Readers (Context => Context); return; end if; if Timeout = 0 then C_Timeout := Thin.INFINITE; end if; if Conditions.Data = VORCP.Empty_Vector then return; else Res := Thin.SCardGetStatusChange (hContext => Context.hContext, dwTimeout => C_Timeout, rgReaderStates => C_States (C_States'First)'Access, cReaders => Thin.DWORD (C_States'Last)); end if; if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Status change detection failed"); end if; Store_Error (Code => Res); -- Update Ada type with values returned by C API function VORCP.Iterate (Container => Conditions.Data, Process => Update_Status_Set'Access); -- Free C_States Convert.Free (Name => C_States); end Status_Change; ------------------------------------------------------------------------- procedure Store_Error (Code : Thin.Return_Code) is begin Last_Return_Code := Code; end Store_Error; ------------------------------------------------------------------------- function To_Atr (Bytes : Byte_Set) return ATR is New_Atr : ATR; Temp_Set : Byte_Set (ATR_Index'Range) := (others => Thin.Null_Byte); begin -- Raise exception if Byte_Set is too big. if Bytes'Length > (ATR_Index'Last + 1) then raise Bytes_Too_Big; end if; -- Store Byte_Set in ATR_Type and set length accordingly. Temp_Set (ATR_Index'First .. Bytes'Length - 1) := Bytes; New_Atr.Data := ATR_Data_Type (Temp_Set); New_Atr.Size := Bytes'Length; return New_Atr; end To_Atr; ------------------------------------------------------------------------- function To_Reader_ID (Name : String) return Reader_ID is begin return Reader_ID'(To_Unbounded_String (Name)); end To_Reader_ID; ------------------------------------------------------------------------- procedure Transmit (Card : SCard.Card; Send_Buffer : Byte_Set; Recv_Pci : in out IO_Request; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural) is begin Transmit (Card => Card, Send_Buffer => Send_Buffer, Send_Len => Send_Buffer'Length, Recv_Pci => Recv_Pci, Recv_Buffer => Recv_Buffer, Recv_Len => Recv_Len); end Transmit; ------------------------------------------------------------------------- procedure Transmit (Card : SCard.Card; Send_Buffer : Byte_Set; Send_Len : Natural; Recv_Pci : in out IO_Request; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural) is Res : Thin.DWORD; C_Send_PCI : aliased Thin.SCARD_IO_REQUEST; C_Recv_PCI : aliased Thin.SCARD_IO_REQUEST := Recv_Pci; Bytes_Returned : aliased Thin.DWORD := Thin.DWORD (Recv_Buffer'Length); begin -- Empty send buffer makes no sense, return without doing anything if Send_Buffer = Null_Byte_Set then return; end if; -- Assign correct send PCI depending on active proto of card C_Send_PCI := Get_PCI (Card => Card); Thin.SCardTransmit (returnValue => Res, hCard => Card.hCard, pioSendPci => C_Send_PCI'Access, pbSendBuffer => Thin.Byte_Array (Send_Buffer), cbSendLength => Thin.DWORD (Send_Len), pioRecvPci => C_Recv_PCI'Access, pbRecvBuffer => Thin.Byte_Array (Recv_Buffer), pcbRecvLength => Bytes_Returned'Access); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Transmit failed"); end if; Store_Error (Code => Res); Recv_Pci := C_Recv_PCI; Recv_Len := Natural (Bytes_Returned); end Transmit; ------------------------------------------------------------------------- procedure Wait_For_Readers (Context : SCard.Context) is Res : Thin.DWORD; begin Res := Thin.SCardGetStatusChange (hContext => Context.hContext, dwTimeout => Thin.INFINITE, rgReaderStates => null); if Res /= Thin.SCARD_S_SUCCESS then SCard_Exception (Code => Res, Message => "Waiting for readers failed"); end if; Store_Error (Code => Res); end Wait_For_Readers; end PCSC.SCard; libpcscada-0.7.1/src/pcsc-scard-monitor.ads0000644000175000017500000001112211664137641017261 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- SCard reader monitoring package. This package provides types and -- functions / procedures to monitor card readers. The abstract type -- Observer can be extended to create new observers for specific reader -- state changes. Observers can be registered to a Reader_Monitor task by -- calling the Register() entry. A running Reader_Monitor task will inform -- all registered observers when a change in reader state occurs. -- -- package PCSC.SCard.Monitor is type Context_Handle is access all SCard.Context; -- Handle to Context object type Observer is abstract tagged record States : Reader_States_Set; -- Reader states this observer is interested in end record; -- Abstract reader observer type. Valid Reader_Monitor observers must -- extend this type. subtype Observer_Class is Observer'Class; -- Observer class subtype function Is_Interested (O : Observer; States : Reader_States_Set) return Boolean; -- Function is used to check whether an observer is interested in one of -- the states in given set. procedure Notify (O : Observer; Condition : Reader_Condition) is abstract; -- This procedure is called to inform an observer about status changes in -- reader states for all states an observer is interested in. task type Reader_Monitor is entry Init (Context : Context_Handle); -- Initialization entry for a reader monitor task entry Start; -- Start the reader monitor task entry Stop; -- Stop the reader monitor task entry Register (O : Observer_Class); -- Register a new observer to the reader monitor end Reader_Monitor; -- Reader monitoring control task private task type Status_Peeker is entry Run (Peek_Context : Context_Handle); entry Stop; end Status_Peeker; -- Status_Peeker task type. An object of this type can be used to detect -- condition changes for all readers of a SCard.Context. Condition changes -- are detected by calling the SCard.Status_Change procedure. package Vector_Of_Observer_Package is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Observer_Class); package VOOBP renames Vector_Of_Observer_Package; subtype Vector_Of_Observer_Type is VOOBP.Vector; protected type Protected_Observer_Set is entry Insert (Observer : Observer_Class); -- Insert a new observer into set. procedure Notify_All (Condition : Reader_Condition); -- Notify all registered observers that a reader state has changed. private My_Set : Vector_Of_Observer_Type; -- Vector of observers Notifying : Boolean := False; -- Barrier condition to indicate whether a notification is currently in -- progress. end Protected_Observer_Set; -- Protected observer set. Used to store observers which are registered by -- the client code by calling the Register() entry of the Reader_Monitor -- task type. Observer_Set : Protected_Observer_Set; -- Set of registered observers. Accessed by Reader_Monitor and -- Status_Peeker tasks. function Create_Condition (Reader : SCard.Reader_ID) return SCard.Reader_Condition; -- Create a new reader condition object from given reader ID. procedure Update_Reader_Table (Table : in out SCard.Reader_Condition_Set; IDs : SCard.Reader_ID_Set); -- Update given reader condition table with IDs in given reader ID set. New -- readers, which are not already in the condition set 'Table', -- are added by calling Create_Condition(), vanished IDs are removed from -- the reader condition set 'Table'. end PCSC.SCard.Monitor; libpcscada-0.7.1/src/pcsc-thin-ifdhandler.ads0000644000175000017500000000405511664137641017547 0ustar reetreet-- -- Copyright (c) 2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- Thin binding to the IFD handler API. -- -- package PCSC.Thin.IFDHandler is subtype RESPONSECODE is C.long; -- IFD response codes IFD_SUCCESS : constant := 0; -- No error IFD_ERROR_TAG : constant := 600; -- Tag unknown TAG_IFD_ATR : constant := 16#0303#; -- ATR TAG_IFD_SLOTNUM : constant := 16#0180#; -- Select a slot TAG_IFD_SLOT_THREAD_SAFE : constant := 16#0FAC#; -- Support access to different slots of the reader TAG_IFD_THREAD_SAFE : constant := 16#0FAD#; -- Driver is thread safe TAG_IFD_SLOTS_NUMBER : constant := 16#0FAE#; -- Number of slots of the reader TAG_IFD_SIMULTANEOUS_ACCESS : constant := 16#0FAF#; -- Number of readers the driver can manage TAG_IFD_POLLING_THREAD : constant := 16#0FB0#; -- Driver uses a polling thread TAG_IFD_POLLING_THREAD_KILLABLE : constant := 16#0FB1#; -- The polling thread can be killed type SCARD_IO_HEADER is record Protocol : DWORD; Length : DWORD; end record; type PSCARD_IO_HEADER is access SCARD_IO_HEADER; end PCSC.Thin.IFDHandler; libpcscada-0.7.1/src/pcsc-thin.adb0000644000175000017500000000216311664137641015426 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Publ License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- package body PCSC.Thin is ------------------------------------------------------------------------- function SCARD_CTL_CODE (Code : DWORD) return DWORD is use type Interfaces.C.unsigned_long; begin return 16#4200_0000# + Code; end SCARD_CTL_CODE; end PCSC.Thin; libpcscada-0.7.1/src/pcsc-scard-conversion.ads0000644000175000017500000002045011664137641017763 0ustar reetreet-- -- Copyright (c) 2008-2009, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Publ License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- This package contains all mapping information and related conversion -- helper functions to convert types from Ada to C and vice versa. The -- package is declared private and cannot be included from the client code. -- -- with Interfaces.C.Strings; with PCSC.Thin.Reader; private package PCSC.SCard.Conversion is C_Scope : constant array (Scope) of Thin.DWORD := (Scope_User => Thin.SCARD_SCOPE_USER, Scope_Terminal => Thin.SCARD_SCOPE_TERMINAL, Scope_System => Thin.SCARD_SCOPE_SYSTEM); -- Map Scope to corresponding C values C_Mode : constant array (Mode) of Thin.DWORD := (Share_Exclusive => Thin.SCARD_SHARE_EXCLUSIVE, Share_Shared => Thin.SCARD_SHARE_SHARED, Share_Direct => Thin.SCARD_SHARE_DIRECT); -- Map Mode to corresponding C values C_Proto : constant array (Proto) of Thin.DWORD := (Proto_Undefined => Thin.SCARD_PROTOCOL_UNDEFINED, Proto_Unset => Thin.SCARD_PROTOCOL_UNSET, Proto_T0 => Thin.SCARD_PROTOCOL_T0, Proto_T1 => Thin.SCARD_PROTOCOL_T1, Proto_RAW => Thin.SCARD_PROTOCOL_RAW, Proto_T15 => Thin.SCARD_PROTOCOL_T15); -- Map Proto to corresponding C values C_Action : constant array (Action) of Thin.DWORD := (Leave_Card => Thin.SCARD_LEAVE_CARD, Reset_Card => Thin.SCARD_RESET_CARD, Unpower_Card => Thin.SCARD_UNPOWER_CARD, Eject_Card => Thin.SCARD_EJECT_CARD); -- Map Action to corresponding C values C_Card_State : constant array (Card_State) of Thin.DWORD := (S_Card_Unknown => Thin.SCARD_UNKNOWN, S_Card_Absent => Thin.SCARD_ABSENT, S_Card_Present => Thin.SCARD_PRESENT, S_Card_Swallowed => Thin.SCARD_SWALLOWED, S_Card_Powered => Thin.SCARD_POWERED, S_Card_Negotiable => Thin.SCARD_NEGOTIABLE, S_Card_Specific => Thin.SCARD_SPECIFIC); -- Map Card_State to corresponding C values. C_Reader_State : constant array (Reader_State) of Thin.DWORD := (S_Reader_Unaware => Thin.SCARD_STATE_UNAWARE, S_Reader_Ignore => Thin.SCARD_STATE_IGNORE, S_Reader_Changed => Thin.SCARD_STATE_CHANGED, S_Reader_Unknown => Thin.SCARD_STATE_UNKNOWN, S_Reader_Unavailable => Thin.SCARD_STATE_UNAVAILABLE, S_Reader_Empty => Thin.SCARD_STATE_EMPTY, S_Reader_Present => Thin.SCARD_STATE_PRESENT, S_Reader_Atrmatch => Thin.SCARD_STATE_ATRMATCH, S_Reader_Exclusive => Thin.SCARD_STATE_EXCLUSIVE, S_Reader_Inuse => Thin.SCARD_STATE_INUSE, S_Reader_Mute => Thin.SCARD_STATE_MUTE, S_Reader_Unpowered => Thin.SCARD_STATE_UNPOWERED); -- Map Reader_State to corresponding C values C_PCI : constant array (PCI) of Thin.SCARD_IO_REQUEST := (PCI_T0 => Thin.SCARD_PCI_T0, PCI_T1 => Thin.SCARD_PCI_T1, PCI_RAW => Thin.SCARD_PCI_RAW); -- Map PCI to corresponding C SCARD_IO_REQUESTs package TR renames Thin.Reader; C_Attr : constant array (Attribute) of Thin.DWORD := (Attr_Vendor_Name => TR.SCARD_ATTR_VENDOR_NAME, Attr_Vendor_IFD_Type => TR.SCARD_ATTR_VENDOR_IFD_TYPE, Attr_Vendor_IFD_Version => TR.SCARD_ATTR_VENDOR_IFD_VERSION, Attr_Vendor_IFD_Serial => TR.SCARD_ATTR_VENDOR_IFD_SERIAL_NO, Attr_Channel_ID => TR.SCARD_ATTR_CHANNEL_ID, Attr_Default_CLK => TR.SCARD_ATTR_DEFAULT_CLK, Attr_Max_CLK => TR.SCARD_ATTR_MAX_CLK, Attr_Default_Data_Rate => TR.SCARD_ATTR_DEFAULT_DATA_RATE, Attr_Max_Data_Rate => TR.SCARD_ATTR_MAX_DATA_RATE, Attr_Max_IFSD => TR.SCARD_ATTR_MAX_IFSD, Attr_Power_Mgmt_Support => TR.SCARD_ATTR_POWER_MGMT_SUPPORT, Attr_Characteristics => TR.SCARD_ATTR_CHARACTERISTICS, Attr_Current_Protocol_Type => TR.SCARD_ATTR_CURRENT_PROTOCOL_TYPE, Attr_Current_CLK => TR.SCARD_ATTR_CURRENT_CLK, Attr_Current_F => TR.SCARD_ATTR_CURRENT_F, Attr_Current_D => TR.SCARD_ATTR_CURRENT_D, Attr_Current_N => TR.SCARD_ATTR_CURRENT_N, Attr_Current_W => TR.SCARD_ATTR_CURRENT_W, Attr_Current_IFSC => TR.SCARD_ATTR_CURRENT_IFSC, Attr_Current_IFSD => TR.SCARD_ATTR_CURRENT_IFSD, Attr_Current_BWT => TR.SCARD_ATTR_CURRENT_BWT, Attr_Current_CWT => TR.SCARD_ATTR_CURRENT_CWT, Attr_Current_EBC_Encoding => TR.SCARD_ATTR_CURRENT_EBC_ENCODING, Attr_Extended_BWT => TR.SCARD_ATTR_EXTENDED_BWT, Attr_ICC_Presence => TR.SCARD_ATTR_ICC_PRESENCE, Attr_ICC_Interface_Status => TR.SCARD_ATTR_ICC_INTERFACE_STATUS, Attr_Current_IO_State => TR.SCARD_ATTR_CURRENT_IO_STATE, Attr_ATR_String => TR.SCARD_ATTR_ATR_STRING, Attr_ICC_Type_Per_ATR => TR.SCARD_ATTR_ICC_TYPE_PER_ATR, Attr_ESC_Preset => TR.SCARD_ATTR_ESC_RESET, Attr_ESC_Cancel => TR.SCARD_ATTR_ESC_CANCEL, Attr_ESC_Authrequest => TR.SCARD_ATTR_ESC_AUTHREQUEST, Attr_Maxinput => TR.SCARD_ATTR_MAXINPUT, Attr_Device_Unit => TR.SCARD_ATTR_DEVICE_UNIT, Attr_Device_In_Use => TR.SCARD_ATTR_DEVICE_IN_USE, Attr_Device_Friendly_Name_A => TR.SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, Attr_Device_System_Name_A => TR.SCARD_ATTR_DEVICE_SYSTEM_NAME_A, Attr_Device_Friendly_Name_W => TR.SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, Attr_Device_System_Name_W => TR.SCARD_ATTR_DEVICE_SYSTEM_NAME_W, Attr_Supress_T1_IFS_Request => TR.SCARD_ATTR_SUPRESS_T1_IFS_REQUEST); -- Map Attribute to corresponding C values procedure Free (Name : in out Thin.READERSTATE_Array); -- Free C Array of READERSTATES. function Slice_Readerstring (To_Slice : String) return Reader_ID_Set; -- Slice reader string returned from thin binding and create vector of -- reader names. The string to slice has a format like: -- Reader A1\0Reader B1\0Reader C1\0\0 -- \0 is used as separator, \0\0 as string termination. -- -- If an invalid string is passed to Slice_Readerstring, an empty reader -- ID set is returned. In this context, invalid means that the To_Slice -- argument is not in the format described above (e.g. no double NUL -- termination). function To_Ada (C_Protocol : Thin.DWORD) return Proto; -- Return Ada style Proto for C_Protocol (DWORD). function To_Ada (C_Cardstate : Thin.DWORD) return Card_States_Set; -- Return Ada style array of card states for C_Cardstate (DWORD). function To_Ada (C_Readerstate : Thin.DWORD) return Reader_States_Set; -- Return Ada style reader states set for C_Readerstate (DWORD). function To_C (Conditions : Reader_Condition_Set) return Thin.READERSTATE_Array; -- Convert Ada type Reader_Condition_Set to the corresponding C -- READERSTATE_Array. Memory allocated by the array must be freed by -- calling Free (Thin.READERSTATE_Array) after usage. function To_Chars_Ptr (Reader : Reader_ID) return Interfaces.C.Strings.chars_ptr; -- Return a new C compatible string from reader ID. The allocated memory -- must be freed by calling Interfaces.C.Strings.Free. end PCSC.SCard.Conversion; libpcscada-0.7.1/src/pcsc-scard.ads0000644000175000017500000004605711664137641015613 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- PC/SC thick-binding package. Provides abstraction from the C style -- functions and types provided in the thin binding in @PCSC.Thin@. -- -- with Ada.Containers.Indefinite_Vectors; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with PCSC.Thin; package PCSC.SCard is type Context is limited private; -- This is the PC/SC-Context. This object is initialized by -- Establish_Context below and is used with all services. type Card is limited private; -- SCard-Handler, returned by Connect. Used to access a specific smartcard. type Byte_Set is array (Natural range <>) of aliased Thin.Byte; -- Byte_Sets are used to send and receive data to/from SCard-Readers. Null_Byte_Set : constant Byte_Set; -- Empty Byte_Set type ATR is private; -- Card ATR type Null_ATR : constant ATR; -- Null initialized ATR type Reader_ID is private; -- Reader friendly name Null_Reader_ID : constant Reader_ID; -- Empty reader ID type Reader_ID_Set is tagged private; -- Set of ReaderIDs type Scope is (Scope_User, -- Scope in user space Scope_Terminal, -- Scope in terminal Scope_System -- Scope in system ); -- Possible scopes for a PC/SC-context type Mode is (Share_Exclusive, -- Exclusive mode only Share_Shared, -- Shared mode only Share_Direct -- Raw mode only ); -- Possible share Modes for SCard connects type Proto is (Proto_Undefined, -- Protocol not set Proto_Unset, -- Backward compatibility Proto_T0, -- T=0 active protocol Proto_T1, -- T=1 active protocol Proto_RAW, -- Raw active protocol Proto_T15 -- T=15 protocol ); -- Possible Protos for SCard connects type Action is (Leave_Card, -- Do nothing on close Reset_Card, -- Reset on close Unpower_Card, -- Power down on close Eject_Card -- Eject on close ); -- Possible card Actions type Card_State is (S_Card_Unknown, -- Unknown state S_Card_Absent, -- Card is absent S_Card_Present, -- Card is present S_Card_Swallowed, -- Card not powered S_Card_Powered, -- Card is powered S_Card_Negotiable, -- Ready for PTS S_Card_Specific -- PTS has been set ); -- Card states type Card_States_Set is tagged private; -- Set of card states type Reader_State is (S_Reader_Unaware, -- App wants status S_Reader_Ignore, -- Ignore this reader S_Reader_Changed, -- State has changed S_Reader_Unknown, -- Reader unknown S_Reader_Unavailable, -- Status unavailable S_Reader_Empty, -- Card removed S_Reader_Present, -- Card inserted S_Reader_Atrmatch, -- ATR matches card S_Reader_Exclusive, -- Exclusive Mode S_Reader_Inuse, -- Shared Mode S_Reader_Mute, -- Unresponsive card S_Reader_Unpowered -- Unpowered card ); -- Reader / Card states type Reader_States_Set is tagged private; -- Set of reader states type Reader_Condition is record Name : Reader_ID := Null_Reader_ID; Current_State : Reader_States_Set; Event_State : Reader_States_Set; Event_Counter : Natural := 0; Card_ATR : ATR := Null_ATR; end record; -- Reader condition type for status change handling. Current_State defines -- the current assumed state. Event_State and Card_ATR is updated by -- calling the Status_Change() procedure. Event_Counter stores the event -- count for the reader identified by 'Name'. type Reader_Condition_Handle is access all Reader_Condition; -- Handle to Reader_Condition type. type Reader_Condition_Set is tagged private; -- Set of reader status types subtype IO_Request is Thin.SCARD_IO_REQUEST; -- Thick binding IO request subtype, used in Transmit() procedure type PCI is (PCI_T0, -- (PCI) for T=0 PCI_T1, -- (PCI) for T=1 PCI_RAW -- (PCI) for RAW protocol ); -- Protocol control information types type Attribute is (Attr_Vendor_Name, Attr_Vendor_IFD_Type, Attr_Vendor_IFD_Version, Attr_Vendor_IFD_Serial, Attr_Channel_ID, Attr_Default_CLK, Attr_Max_CLK, Attr_Default_Data_Rate, Attr_Max_Data_Rate, Attr_Max_IFSD, Attr_Power_Mgmt_Support, Attr_Characteristics, Attr_Current_Protocol_Type, Attr_Current_CLK, Attr_Current_F, Attr_Current_D, Attr_Current_N, Attr_Current_W, Attr_Current_IFSC, Attr_Current_IFSD, Attr_Current_BWT, Attr_Current_CWT, Attr_Current_EBC_Encoding, Attr_Extended_BWT, Attr_ICC_Presence, Attr_ICC_Interface_Status, Attr_Current_IO_State, Attr_ATR_String, Attr_ICC_Type_Per_ATR, Attr_ESC_Preset, Attr_ESC_Cancel, Attr_ESC_Authrequest, Attr_Maxinput, Attr_Device_Unit, Attr_Device_In_Use, Attr_Device_Friendly_Name_A, Attr_Device_System_Name_A, Attr_Device_Friendly_Name_W, Attr_Device_System_Name_W, Attr_Supress_T1_IFS_Request); -- Possible attributes for Get_Attribute procedure procedure Add (States : in out Card_States_Set; State : Card_State); -- Add a new card state to card states set. procedure Add (States : in out Reader_States_Set; State : Reader_State); -- Add a new reader state to reader states set. procedure Add (Set : in out Reader_Condition_Set; Status : Reader_Condition); -- Add a new reader to reader condition array. State specifies the assumed -- initial state of the reader/card. procedure Begin_Transaction (Card : SCard.Card); -- This procedure establishes a temporary exclusive access mode for doing -- a series of commands or transactions with a SCard. procedure Cancel (Context : SCard.Context); -- This procedure cancels all pending blocking requests on the -- Status_Change() procedure for a given SCard 'Context'. procedure Connect (Context : SCard.Context; Card : in out SCard.Card; Reader : Reader_ID := Null_Reader_ID; Mode : SCard.Mode := Share_Shared); -- Connect to a SCard identified by Reader (Reader_ID). Handle to connected -- SCard will be stored in 'Card' parameter. procedure Control (Card : SCard.Card; Code : Natural; Send_Buffer : Byte_Set := Null_Byte_Set; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural); -- This procedure sends a control command to the reader connected to by -- Connect(). It returns the the control response in Recv_Buffer. procedure Disconnect (Card : SCard.Card; Action : SCard.Action); -- This procedure terminates a connection to a card. function Empty (Set : Reader_ID_Set) return Boolean; -- This function returns True if the reader ID set contains no readers. procedure End_Transaction (Card : SCard.Card; Action : SCard.Action); -- This procedure ends a previously started transaction. procedure Establish_Context (Context : in out SCard.Context; Scope : SCard.Scope); -- Establish PC/SC-context. Possible Scope values are defined in the -- SCard_Scope type. function Find (Set : Reader_Condition_Set; Reader_ID : SCard.Reader_ID) return Boolean; -- Search a given Reader_ID in Reader_Condition_Set. If found, True is -- returned, False if not found. function First_Index (Set : Reader_ID_Set) return Natural; -- Returns the first index of the given reader ID set. function First_Index (Set : Reader_States_Set) return Natural; -- Returns the first index of the given reader states set. function First_Index (Set : Reader_Condition_Set) return Natural; -- Returns the first index of the given reader condition set. function First_Item (Set : Reader_ID_Set) return Reader_ID; -- Returns the first reader ID from the given reader ID set. function First_Item (Set : Reader_States_Set) return Reader_State; -- Returns the first reader state from the given reader states set. function Get (Set : Reader_ID_Set; Index : Natural) return Reader_ID; -- Returns the reader ID at given index in the set. function Get (Set : Reader_States_Set; Index : Natural) return Reader_State; -- Returns the reader state at given index in the set. function Get (Set : Reader_Condition_Set; Index : Natural) return Reader_Condition; -- Returns the reader condition at given index in the set. function Get_Active_Proto (Card : SCard.Card) return Proto; -- Return protocol in use for a given card. procedure Get_Attribute (Card : SCard.Card; Attr : Attribute; Recv_Buffer : in out Byte_Set); -- This procedure gets an attribute from the IFD handler. Call -- Init_Attribute_Set prior to this function to allocate the correct byte -- set for the call. function Get_PCI (Card : SCard.Card) return Thin.SCARD_IO_REQUEST; -- Return PCI to use for a given card. If no valid PCI for a proto is -- found, a No_PCI_for_Proto exception will be thrown. function Get_Return_Code return String; -- Return string representation of last stored return code. function Init_Attribute_Set (Card : SCard.Card; Attr : Attribute) return Byte_Set; -- This function returns an Null_Byte initialized byte set to provide -- storage for an attribute 'Attr'. The byte set can then be used as -- parameter to the Get_Attribute function to actually retrieve the -- attribute data. function Is_In (States : Reader_States_Set; State : Reader_State) return Boolean; -- Function returns True if given reader state is found in the reader -- states set. function Is_In (States : Card_States_Set; State : Card_State) return Boolean; -- Function returns True if given card state is found in the card states -- set. function Is_Valid (Context : SCard.Context) return Boolean; -- Verify that given SCard context is valid. function Last_Index (Set : Reader_ID_Set) return Natural; -- Returns the last index of a reader ID set. function Last_Index (Set : Reader_States_Set) return Natural; -- Returns the last index of a reader states set. function Last_Index (Set : Reader_Condition_Set) return Natural; -- Returns the last index of a reader condition set. function Last_Item (Set : Reader_ID_Set) return Reader_ID; -- Returns the last reader ID in a reader ID set. function Last_Item (Set : Reader_States_Set) return Reader_State; -- Returns the last reader state in a reader states set. function Length (Set : Reader_Condition_Set) return Natural; -- Returns the length of a reader condition set. function List_Readers (Context : SCard.Context) return Reader_ID_Set; -- Return list of all available readers for given PC/SC context. procedure Reconnect (Card : in out SCard.Card; Mode : SCard.Mode; Action : SCard.Action); -- This procedure re-establishes a connection. The Init argument defines -- the desired SCard action to perform on the card/reader. procedure Release_Context (Context : in out SCard.Context); -- Release previously acquired SCard context. procedure Remove (States : in out Reader_States_Set; State : Reader_State); -- Remove reader state from given reader states set. procedure SPE_Exec (Card : in out SCard.Card; Result : in out Byte_Set); -- Request the reader connected to by 'Card' to perform a secure PIN entry -- operation. If not already done by the client code, this procedure will -- use the SPE_Init() procedure to check if the reader supports SPE and to -- initialize the verify ctrl code. If the SPE operation is not supported -- or does not work as expected, an SCard_Not_Supported exception is -- raised. If the SPE operation is successful, the bytes returned from the -- reader will be stored in 'Result' byte set. procedure SPE_Init (Card : in out SCard.Card; Result : in out Boolean); -- Procedure checks if a reader connected by 'Card' handle supports SPE -- (secure PIN entry) operation. If it does, 'Result' will be True, -- otherwise 'Result' will be False. function Size (Atr : SCard.ATR := Null_ATR) return Natural; -- Return current size (in bytes) of an ATR as Natural. function Size (Atr : SCard.ATR := Null_ATR) return String; -- Return current size (in bytes) of an ATR as String. procedure Status (Card : SCard.Card; State : out SCard.Card_States_Set; Proto : out SCard.Proto; Atr : out SCard.ATR); -- This procedure checks the current status of the reader connected to by -- 'Card'. Current state, protocol and ATR value of inserted card are -- returned as out parameters. procedure Status_Change (Context : SCard.Context; Timeout : Natural := 0; Conditions : in out Reader_Condition_Set); -- This procedure takes a reader condition set containing reader names -- with their assumed state. It then blocks maximum 'Timeout' milliseconds -- time for a change in state to occur. If no timeout is given, 0 will be -- used, which will block forever. When a status change occurs, the -- Conditions object is updated to reflect the change(s). If this procedure -- is called with an empty Conditions object, Wait_For_Readers() is used -- to wait for a reader to appear, then the procedure returns. procedure Wait_For_Readers (Context : SCard.Context); -- This procedure calls SCardGetStatusChange for reader detection. If there -- is no reader available, the call will block until a reader is connected. -- If there are readers present when this function is called, it will -- return immediately. procedure Transmit (Card : SCard.Card; Send_Buffer : Byte_Set; Recv_Pci : in out IO_Request; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural); -- Transmit buffer to SCard. procedure Transmit (Card : SCard.Card; Send_Buffer : Byte_Set; Send_Len : Natural; Recv_Pci : in out IO_Request; Recv_Buffer : in out Byte_Set; Recv_Len : in out Natural); -- Transmit Send_Len bytes of buffer to SCard. function To_Atr (Bytes : Byte_Set) return ATR; -- Create new ATR object from given byte set. If 'Bytes' is too big to be -- converted into an ATR type, a 'Bytes_Too_Big' exception will be raised. function To_Reader_ID (Name : String) return Reader_ID; -- Returns a new reader ID initialized with 'Name' string. private procedure SCard_Exception (Code : Thin.Return_Code; Message : String); pragma No_Return (SCard_Exception); -- Raise SCard exception if something goes wrong. Last_Return_Code : Thin.Return_Code; -- Holds the return code of the last SCard operation. Get_Return_Code -- can be used to obtain this code. Store_Error should be used to save the -- return code after a thin binding call. procedure Store_Error (Code : Thin.Return_Code); -- Saves the last returned status code. type Context is limited record hContext : aliased Thin.SCARDCONTEXT; end record; type Card is limited record hCard : aliased Thin.SCARDHANDLE; -- Card handle used by the thin binding Active_Proto : aliased Thin.DWORD := Thin.SCARD_PROTOCOL_UNDEFINED; -- Current protocol used by the card Verify_Ctrl : Thin.DWORD := 0; -- Verify control code needed to perform SPE end record; Null_Byte_Set : constant Byte_Set (1 .. 0) := (others => Thin.Null_Byte); subtype ATR_Index is Natural range 0 .. Thin.MAX_ATR_SIZE; type ATR_Byte_Count is range 0 .. Thin.MAX_ATR_SIZE + 1; -- ATR size in bytes. type ATR_Data_Type is new Byte_Set (ATR_Index'Range); -- ATR data: Defines a constrained Byte_Set to store the actual ATR data. type ATR is record Data : ATR_Data_Type; Size : ATR_Byte_Count; end record; Null_ATR : constant ATR := ATR' (Data => ATR_Data_Type'(others => Thin.Null_Byte), Size => 0); -- Reader IDs type Reader_ID is new Unbounded_String; Null_Reader_ID : constant Reader_ID := Reader_ID (Null_Unbounded_String); package Vector_Of_ReaderID_Package is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Reader_ID); package VOIDP renames Vector_Of_ReaderID_Package; subtype Vector_Of_ReaderID_Type is VOIDP.Vector; type Reader_ID_Set is tagged record Data : Vector_Of_ReaderID_Type; end record; -- Card states package Vector_Of_CStates_Package is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Card_State); package VOCSP renames Vector_Of_CStates_Package; subtype Vector_Of_CStates_Type is VOCSP.Vector; type Card_States_Set is tagged record Data : Vector_Of_CStates_Type; end record; -- Reader states package Vector_Of_RStates_Package is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Reader_State); package VORSP renames Vector_Of_RStates_Package; subtype Vector_Of_RStates_Type is VORSP.Vector; type Reader_States_Set is tagged record Data : Vector_Of_RStates_Type; end record; -- Reader status package Vector_Of_Status_Package is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Reader_Condition); package VORCP renames Vector_Of_Status_Package; subtype Vector_Of_Condition_Type is VORCP.Vector; type Reader_Condition_Set is tagged record Data : Vector_Of_Condition_Type; end record; end PCSC.SCard; libpcscada-0.7.1/src/pcsc-scard-monitor.adb0000644000175000017500000002022511664137641017244 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- pragma Detect_Blocking; with Ada.Text_IO; with Ada.Exceptions; package body PCSC.SCard.Monitor is ------------------------------------------------------------------------- function Create_Condition (Reader : SCard.Reader_ID) return SCard.Reader_Condition is New_Condition : SCard.Reader_Condition; begin New_Condition.Name := Reader; New_Condition.Current_State.Add (State => SCard.S_Reader_Unaware); return New_Condition; end Create_Condition; ------------------------------------------------------------------------- function Is_Interested (O : Observer; States : Reader_States_Set) return Boolean is use type VORSP.Cursor; Position : VORSP.Cursor := O.States.Data.First; begin while VORSP.Has_Element (Position) loop if States.Data.Find (Item => VORSP.Element (Position)) /= VORSP.No_Element then return True; end if; VORSP.Next (Position); end loop; return False; end Is_Interested; ------------------------------------------------------------------------- task body Reader_Monitor is Current_Context : Context_Handle; -- Handle to current SCard.Context in use Peeker : Status_Peeker; -- Status peeker task Stop_Monitor : Boolean := False; -- Flag to signal monitor shutdown begin accept Init (Context : Context_Handle) do Current_Context := Context; end Init; loop exit when Stop_Monitor; select accept Start; -- Start status peeker task Peeker.Run (Peek_Context => Current_Context); or when not Stop_Monitor => accept Stop do Stop_Monitor := True; if SCard.Is_Valid (Context => Current_Context.all) then SCard.Cancel (Context => Current_Context.all); end if; end Stop; -- Stop status peeker task Peeker.Stop; or when not Stop_Monitor => accept Register (O : Observer_Class) do Observer_Set.Insert (Observer => O); end Register; end select; end loop; end Reader_Monitor; ------------------------------------------------------------------------- task body Status_Peeker is Reader_IDs : SCard.Reader_ID_Set; Reader_IDnew : SCard.Reader_ID_Set; Reader_Table : SCard.Reader_Condition_Set; Current_Context : Context_Handle; Stop_Peeker : Boolean := False; -- Flag to signal peeker shutdown begin loop exit when Stop_Peeker; select accept Run (Peek_Context : Context_Handle) do Current_Context := Peek_Context; end Run; -- Main status detection loop loop SCard.Status_Change (Context => Current_Context.all, Conditions => Reader_Table); -- Check for new readers; if new ones are found, add them to -- the Reader_Table. If none found, an exception is thrown. begin Reader_IDnew := SCard.List_Readers (Context => Current_Context.all); if Reader_IDnew /= Reader_IDs then Update_Reader_Table (Table => Reader_Table, IDs => Reader_IDnew); Reader_IDs := Reader_IDnew; end if; exception when SCard_Error => -- No readers present, set empty vectors -- TODO: add possibility to notify this event Reader_Table.Data := VORCP.Empty_Vector; Reader_IDs.Data := VOIDP.Empty_Vector; end; -- Loop through reader table and check for state -- S_Reader_Changed declare Position : VORCP.Cursor := Reader_Table.Data.First; Item : Reader_Condition; begin while VORCP.Has_Element (Position) loop Item := VORCP.Element (Position); if Item.Event_State.Is_In (State => SCard.S_Reader_Changed) then -- Event_State contains S_Reader_Changed, update -- Current_State with new Event_State. Item.Event_State.Remove (State => SCard.S_Reader_Changed); Item.Current_State := Item.Event_State; Reader_Table.Data.Replace_Element (Position => Position, New_Item => Item); -- Notify all interested observers Observer_Set.Notify_All (Condition => Item); end if; VORCP.Next (Position); end loop; end; end loop; or when not Stop_Peeker => accept Stop do Stop_Peeker := True; end Stop; end select; end loop; exception when E : others => Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (X => E)); end Status_Peeker; ------------------------------------------------------------------------- protected body Protected_Observer_Set is entry Insert (Observer : Observer_Class) when not Notifying is begin My_Set.Append (New_Item => Observer); end Insert; procedure Notify_All (Condition : Reader_Condition) is Position : VOOBP.Cursor := My_Set.First; begin Notifying := True; while VOOBP.Has_Element (Position) loop if VOOBP.Element (Position).Is_Interested (States => Condition.Current_State) then VOOBP.Element (Position).Notify (Condition); end if; VOOBP.Next (Position); end loop; Notifying := False; end Notify_All; end Protected_Observer_Set; ------------------------------------------------------------------------- procedure Update_Reader_Table (Table : in out SCard.Reader_Condition_Set; IDs : SCard.Reader_ID_Set) is use type VOIDP.Cursor; Position : VORCP.Cursor := Table.Data.First; Item : Reader_Condition; begin -- Remove vanished readers while VORCP.Has_Element (Position) loop Item := VORCP.Element (Position); if IDs.Data.Find (Item.Name) = VOIDP.No_Element then -- TODO: add possibility to notify a reader vanished event Table.Data.Delete (Position); end if; VORCP.Next (Position); end loop; -- Add new readers to table for R in Natural range IDs.First_Index .. IDs.Last_Index loop -- Skip already known readers if not Table.Find (Reader_ID => IDs.Get (R)) then -- TODO: add possibility to notify a new reader event Table.Add (Status => Create_Condition (Reader => IDs.Get (R))); end if; end loop; end Update_Reader_Table; end PCSC.SCard.Monitor; libpcscada-0.7.1/src/pcsc-thin.ads0000644000175000017500000004437511664137641015462 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- PC/SC thin-binding package specification. Imports PC/SC functions and -- provides Ada definitions of types needed to interface with the C API -- of PC/SC. You should not use this package directly, use the more abstract -- thick binding provided in the @PCSC.Scard@ package. -- -- with Interfaces.C; with Interfaces.C.Strings; package PCSC.Thin is package C renames Interfaces.C; -- Type definitions subtype LONG is C.long; subtype DWORD is C.unsigned_long; subtype LPSTR is C.Strings.chars_ptr; subtype UCHAR is C.unsigned_char; type PDWORD is access DWORD; -- Byte'n'Hex subtype Byte is Interfaces.Unsigned_8; type Byte_Array is array (Natural range <>) of aliased Byte; type Byte_Access is access all Byte; Null_Byte : constant Byte; Null_Byte_Array : constant Byte_Array; -- ATR MAX_ATR_SIZE : constant := 32; -- Maximum ATR size subtype ATR is Byte_Array (0 .. MAX_ATR_SIZE); -- Binary ATR data type ATR_Access is access ATR; -- Access to ATR data array Null_ATR : constant ATR; -- Null initialized ATR MAX_BUFFER_SIZE : constant := 264; -- Maximum size of a buffer type void is null record; pragma Convention (C, void); type LPVOID is access void; pragma Convention (C, LPVOID); type LPCVOID is access constant void; pragma Convention (C, LPCVOID); subtype SCARDCONTEXT is LONG; -- Context handling related definitions subtype SCARDHANDLE is LONG; -- Smartcard handle type READERSTATE is record szReader : LPSTR := C.Strings.Null_Ptr; pvUserData : LPCVOID := null; dwCurrentState : DWORD := 0; dwEventState : DWORD := 0; cbAtr : DWORD := MAX_ATR_SIZE; rgbAtr : ATR; end record; -- Reader state type type READERSTATE_Array is array (C.size_t range <>) of aliased READERSTATE; -- Array of reader states type SCARD_IO_REQUEST is record dwProtocol : DWORD := 0; cbPciLength : DWORD := 0; end record; -- SCard io request structure subtype Return_Code is DWORD range 16#0000_0000# .. 16#8010_0069#; -- SCard error return codes SCARD_S_SUCCESS : constant := 16#0000_0000#; -- No error was encountered SCARD_F_INTERNAL_ERROR : constant := 16#8010_0001#; -- An internal consistency check failed SCARD_E_CANCELLED : constant := 16#8010_0002#; -- The action was cancelled by an SCardCancel request SCARD_E_INVALID_HANDLE : constant := 16#8010_0003#; -- The supplied handle was invalid SCARD_E_INVALID_PARAMETER : constant := 16#8010_0004#; -- One or more of the supplied parameters could not be properly -- interpreted SCARD_E_INVALID_TARGET : constant := 16#8010_0005#; -- Registry startup information is missing or invalid SCARD_E_NO_MEMORY : constant := 16#8010_0006#; -- Not enough memory available to complete this command SCARD_F_WAITED_TOO_LONG : constant := 16#8010_0007#; -- An internal consistency timer has expired SCARD_E_INSUFFICIENT_BUFFER : constant := 16#8010_0008#; -- The data buffer to receive returned data is too small for the returned -- data SCARD_E_UNKNOWN_READER : constant := 16#8010_0009#; -- The specified reader name is not recognized SCARD_E_TIMEOUT : constant := 16#8010_000A#; -- The user-specified timeout value has expired SCARD_E_SHARING_VIOLATION : constant := 16#8010_000B#; -- The smart card cannot be accessed because of other connections -- outstanding SCARD_E_NO_SMARTCARD : constant := 16#8010_000C#; -- The operation requires a Smart Card, but no Smart Card is currently in -- the device SCARD_E_UNKNOWN_CARD : constant := 16#8010_000D#; -- The specified smart card name is not recognized SCARD_E_CANT_DISPOSE : constant := 16#8010_000E#; -- The system could not dispose of the media in the requested manner SCARD_E_PROTO_MISMATCH : constant := 16#8010_000F#; -- The requested protocols are incompatible with the protocol currently in -- use with the smart card SCARD_E_NOT_READY : constant := 16#8010_0010#; -- The reader or smart card is not ready to accept commands SCARD_E_INVALID_VALUE : constant := 16#8010_0011#; -- One or more of the supplied parameters values could not be properly -- interpreted SCARD_E_SYSTEM_CANCELLED : constant := 16#8010_0012#; -- The action was cancelled by the system, presumably to log off or shut -- down SCARD_F_COMM_ERROR : constant := 16#8010_0013#; -- An internal communications error has been detected SCARD_F_UNKNOWN_ERROR : constant := 16#8010_0014#; -- An internal error has been detected, but the source is unknown SCARD_E_INVALID_ATR : constant := 16#8010_0015#; -- An ATR obtained from the registry is not a valid ATR string SCARD_E_NOT_TRANSACTED : constant := 16#8010_0016#; -- An attempt was made to end a non-existent transaction SCARD_E_READER_UNAVAILABLE : constant := 16#8010_0017#; -- The specified reader is not currently available for use SCARD_W_UNSUPPORTED_CARD : constant := 16#8010_0065#; -- The reader cannot communicate with the card, due to ATR string -- configuration conflicts SCARD_W_UNRESPONSIVE_CARD : constant := 16#8010_0066#; -- The smart card is not responding to a reset SCARD_W_UNPOWERED_CARD : constant := 16#8010_0067#; -- Power has been removed from the smart card, so that further -- communication is not possible SCARD_W_RESET_CARD : constant := 16#8010_0068#; -- The smart card has been reset, so any shared state information is -- invalid SCARD_W_REMOVED_CARD : constant := 16#8010_0069#; -- The smart card has been removed, so further communication is not -- possible SCARD_E_PCI_TOO_SMALL : constant := 16#8010_0019#; -- The PCI Receive buffer was too small SCARD_E_READER_UNSUPPORTED : constant := 16#8010_001A#; -- The reader driver does not meet minimal requirements for support SCARD_E_DUPLICATE_READER : constant := 16#8010_001B#; -- The reader driver did not produce a unique reader name SCARD_E_CARD_UNSUPPORTED : constant := 16#8010_001C#; -- The smart card does not meet minimal requirements for support SCARD_E_NO_SERVICE : constant := 16#8010_001D#; -- The Smart card resource manager is not running SCARD_E_SERVICE_STOPPED : constant := 16#8010_001E#; -- The Smart card resource manager has shut down SCARD_E_NO_READERS_AVAILABLE : constant := 16#8010_002E#; -- Cannot find a smart card reader SCARD_SCOPE_USER : constant := 16#0000#; -- Scope in user space SCARD_SCOPE_TERMINAL : constant := 16#0001#; -- Scope in terminal SCARD_SCOPE_SYSTEM : constant := 16#0002#; -- Scope in system SCARD_PROTOCOL_UNDEFINED : constant := 16#0000#; -- protocol not set SCARD_PROTOCOL_UNSET : constant := 16#0000#; -- backward compat SCARD_PROTOCOL_T0 : constant := 16#0001#; -- T=0 active protocol SCARD_PROTOCOL_T1 : constant := 16#0002#; -- T=1 active protocol SCARD_PROTOCOL_RAW : constant := 16#0004#; -- Raw active protocol SCARD_PROTOCOL_T15 : constant := 16#0008#; -- T=15 protocol SCARD_SHARE_EXCLUSIVE : constant := 16#0001#; -- Exclusive mode only SCARD_SHARE_SHARED : constant := 16#0002#; -- Shared mode only SCARD_SHARE_DIRECT : constant := 16#0003#; -- Raw mode only SCARD_LEAVE_CARD : constant := 16#0000#; -- Do nothing on close SCARD_RESET_CARD : constant := 16#0001#; -- Reset on close SCARD_UNPOWER_CARD : constant := 16#0002#; -- Power down on close SCARD_EJECT_CARD : constant := 16#0003#; -- Eject on close SCARD_UNKNOWN : constant := 16#0001#; -- Unknown state SCARD_ABSENT : constant := 16#0002#; -- Card is absent SCARD_PRESENT : constant := 16#0004#; -- Card is present SCARD_SWALLOWED : constant := 16#0008#; -- Card not powered SCARD_POWERED : constant := 16#0010#; -- Card is powered SCARD_NEGOTIABLE : constant := 16#0020#; -- Ready for PTS SCARD_SPECIFIC : constant := 16#0040#; -- PTS has been set SCARD_STATE_UNAWARE : constant := 16#0000#; -- App wants status SCARD_STATE_IGNORE : constant := 16#0001#; -- Ignore this reader SCARD_STATE_CHANGED : constant := 16#0002#; -- State has changed SCARD_STATE_UNKNOWN : constant := 16#0004#; -- Reader unknown SCARD_STATE_UNAVAILABLE : constant := 16#0008#; -- Status unavailable SCARD_STATE_EMPTY : constant := 16#0010#; -- Card removed SCARD_STATE_PRESENT : constant := 16#0020#; -- Card inserted SCARD_STATE_ATRMATCH : constant := 16#0040#; -- ATR matches card SCARD_STATE_EXCLUSIVE : constant := 16#0080#; -- Exclusive Mode SCARD_STATE_INUSE : constant := 16#0100#; -- Shared Mode SCARD_STATE_MUTE : constant := 16#0200#; -- Unresponsive card SCARD_STATE_UNPOWERED : constant := 16#0400#; -- Unpowered card SCARD_PCI_T0 : aliased SCARD_IO_REQUEST := (dwProtocol => SCARD_PROTOCOL_T0, cbPciLength => 8); -- Protocol control information (PCI) for T=0 SCARD_PCI_T1 : aliased SCARD_IO_REQUEST := (dwProtocol => SCARD_PROTOCOL_T1, cbPciLength => 8); -- Protocol control information (PCI) for T=1 SCARD_PCI_RAW : aliased SCARD_IO_REQUEST := (dwProtocol => SCARD_PROTOCOL_RAW, cbPciLength => 8); -- Protocol control information (PCI) for RAW protocol INFINITE : constant := 16#FFFF_FFFF#; -- Infinite timeout (PC/SC Lite specific extension) function SCardEstablishContext (dwScope : DWORD; pvReserved1 : LPCVOID := null; pvReserver2 : LPCVOID := null; phContext : access SCARDCONTEXT) return DWORD; -- Establish PC/SC context function SCardReleaseContext (hContext : SCARDCONTEXT) return DWORD; -- Release PC/SC context function SCardIsValidContext (hContext : SCARDCONTEXT) return DWORD; -- Validate PC/SC context function SCardConnect (hContext : SCARDCONTEXT; szReader : LPSTR; dwShareMode : DWORD; dwPreferredProtocols : DWORD; phCard : access SCARDHANDLE; pdwActiveProtocol : access DWORD) return DWORD; -- Connect to specific SCard function SCardReconnect (hCard : SCARDHANDLE; dwShareMode : DWORD; dwPreferredProtocols : DWORD; dwInitialization : DWORD; pdwActiveProtocol : access DWORD) return DWORD; -- Recconnect to specific SCard function SCardDisconnect (hCard : SCARDHANDLE; dwDisposition : DWORD) return DWORD; -- Disconnect from specific SCard function SCardBeginTransaction (hCard : SCARDHANDLE) return DWORD; -- Begin transaction with specific SCard function SCardEndTransaction (hCard : SCARDHANDLE; dwDisposition : DWORD) return DWORD; -- End transaction with specific SCard function SCardCancelTransaction (hCard : SCARDHANDLE) return DWORD; -- Cancel transaction with specific SCard procedure SCardStatus (returnValue : out DWORD; hCard : SCARDHANDLE; mszReaderNames : LPSTR; pcchReaderLen : access DWORD; pdwState : access DWORD; pdwProtocol : access DWORD; pbAtr : out Byte_Array; pcbAtrLen : access DWORD); -- Get status from specific card function SCardGetStatusChange (hContext : SCARDCONTEXT; dwTimeout : DWORD; rgReaderStates : access READERSTATE; cReaders : DWORD := 0) return DWORD; -- Used to track status changes of readers function SCardCancel (hContext : SCARDCONTEXT) return DWORD; -- Cancel all pending blocking requests on the SCardGetStatusChange() -- function function SCardControl (hCard : SCARDHANDLE; dwControlCode : DWORD; pbSendBuffer : access Byte; cbSendLength : DWORD; pbRecvBuffer : access Byte; cbRecvLength : DWORD; lpBytesReturned : access DWORD) return DWORD; -- Send control to card procedure SCardTransmit (returnValue : out DWORD; hCard : SCARDHANDLE; pioSendPci : access SCARD_IO_REQUEST; pbSendBuffer : Byte_Array; cbSendLength : DWORD; pioRecvPci : access SCARD_IO_REQUEST; pbRecvBuffer : out Byte_Array; pcbRecvLength : access DWORD); -- Transmit APDUs to card function SCardListReaders (hContext : SCARDCONTEXT; mszGroups : LPSTR := C.Strings.Null_Ptr; mszReaders : LPSTR; pcchReaders : access DWORD) return DWORD; -- List readers function SCardListReaderGroups (hContext : SCARDCONTEXT; mszGroups : LPSTR; pcchGroups : access DWORD) return DWORD; -- List reader groups function SCardGetAttrib (hCard : SCARDHANDLE; dwAttrId : DWORD; pbAttr : access Byte; pcbAttrLen : access DWORD) return DWORD; -- Get an attribute from the IFD handler function SCardSetAttrib (hCard : SCARDHANDLE; dwAttrId : DWORD; pbAttr : Byte_Array; cbAttrLen : DWORD) return DWORD; -- Set an attribute of the IFD handler function pcsc_stringify_error (status : DWORD) return C.Strings.chars_ptr; -- Get stringified error message function SCARD_CTL_CODE (Code : DWORD) return DWORD; -- Return SCard Control Code for given code. Used to provide source -- compatibility on different platforms. private Null_ATR : constant ATR := (others => 0); Null_Byte : constant Byte := 16#00#; Null_Byte_Array : constant Byte_Array (1 .. 0) := (others => Null_Byte); -- Imports pragma Import (Convention => C, Entity => SCardEstablishContext, External_Name => "SCardEstablishContext"); pragma Import (Convention => C, Entity => SCardReleaseContext, External_Name => "SCardReleaseContext"); pragma Import (Convention => C, Entity => SCardIsValidContext, External_Name => "SCardIsValidContext"); pragma Import (Convention => C, Entity => SCardConnect, External_Name => "SCardConnect"); pragma Import (Convention => C, Entity => SCardReconnect, External_Name => "SCardReconnect"); pragma Import (Convention => C, Entity => SCardDisconnect, External_Name => "SCardDisconnect"); pragma Import (Convention => C, Entity => SCardBeginTransaction, External_Name => "SCardBeginTransaction"); pragma Import (Convention => C, Entity => SCardEndTransaction, External_Name => "SCardEndTransaction"); pragma Import (Convention => C, Entity => SCardCancelTransaction, External_Name => "SCardCancelTransaction"); pragma Import (Convention => C, Entity => SCardStatus, External_Name => "SCardStatus"); pragma Import_Valued_Procedure (Internal => SCardStatus, External => "SCardStatus"); pragma Import (Convention => C, Entity => SCardGetStatusChange, External_Name => "SCardGetStatusChange"); pragma Import (Convention => C, Entity => SCardCancel, External_Name => "SCardCancel"); pragma Import (Convention => C, Entity => SCardControl, External_Name => "SCardControl"); pragma Import (Convention => C, Entity => SCardTransmit, External_Name => "SCardTransmit"); pragma Import_Valued_Procedure (Internal => SCardTransmit, External => "SCardTransmit"); pragma Import (Convention => C, Entity => SCardListReaders, External_Name => "SCardListReaders"); pragma Import (Convention => C, Entity => SCardListReaderGroups, External_Name => "SCardListReaderGroups"); pragma Import (Convention => C, Entity => SCardGetAttrib, External_Name => "SCardGetAttrib"); pragma Import (Convention => C, Entity => SCardSetAttrib, External_Name => "SCardSetAttrib"); pragma Import (C, pcsc_stringify_error); end PCSC.Thin; libpcscada-0.7.1/TODO0000644000175000017500000000162711664137641012773 0ustar reetreetPCSC/Ada TODO List =================== - Improve / optimize Set operations, add unit tests for all set operations. - Add preferred protocols to SCard.Connect procedure - Support 'or' operation for SCard.Connect preferred protocols - Add default options or null/empty types for in params. - Improve SCard.Transmit and corresponding buffer handling. * Remove Recv_Len param. * Allocate memory for buffer inside the binding, client does not know the required size before the call returns. * For that we need Handles and Free() procedures. - Provide To_Byte_Set function which returns a Byte_Set from a String. * e.g. "16 3B 12 28" - Use 'private with' for PCSC.Thin in thick binding. * A thick binding type for Thin.Byte is needed. - Add proper error handling to Reader_Monitor task. - Avoid nested functions / procedures: GCC implements them using trampolines, which requires the stack to be executable. libpcscada-0.7.1/Makefile0000644000175000017500000000617711664137641013750 0ustar reetreet# # Copyright (c) 2008-2009, # Reto Buerki # # This file is part of PCSC/Ada. # # PCSC/Ada is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # PCSC/Ada is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with PCSC/Ada; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, # MA 02110-1301 USA # PREFIX ?= $(HOME)/libraries INCDIR = $(PREFIX)/share/ada/adainclude/pcscada ALIDIR = $(PREFIX)/lib/ada/adalib/pcscada INSTALL = install MAJOR = 0 MINOR = 7 REV = 1 VERSION = $(MAJOR).$(MINOR).$(REV) PCSCADA = libpcscada-$(VERSION) SOURCEDIR = src DOCDIR = doc/html ALI_FILES = lib/*.ali SO_LIBRARY = libpcscada.so.$(VERSION) A_LIBRARY = libpcscada.a TMPDIR = /tmp DISTDIR = $(TMPDIR)/$(PCSCADA) TARBALL = $(PCSCADA).tar.bz2 LIBRARY_KIND = dynamic all: build_lib build_lib: prepare @gnatmake -p -Ppcscada_lib -XPCSCADA_VERSION="$(VERSION)" \ -XLIBRARY_KIND="$(LIBRARY_KIND)" build_utests: prepare @gnatmake -p -Ppcscada_utests build_itests: prepare @gnatmake -p -Ppcscada_itests build_examples: prepare @gnatmake -p -Ppcscada_examples prepare: $(SOURCEDIR)/pcsc-version.ads $(SOURCEDIR)/pcsc-version.ads: @echo "package PCSC.Version is" > $@ @echo " Version_String : constant String :=" >> $@ @echo " \"$(VERSION)\";" >> $@ @echo "end PCSC.Version;" >> $@ clean: @rm -rf obj/* @rm -rf lib/* $(MAKE) -C doc clean distclean: @rm -rf obj @rm -rf lib @rm -rf $(DOCDIR) @rm -f $(SOURCEDIR)/pcsc-version.ads # run unit tests utests: build_utests @obj/utests/runner # run 'integration' tests # you need a reader and smartcard for this to work itests: build_itests @obj/itests/test_pcscada examples: build_examples install: install_lib install_$(LIBRARY_KIND) install_lib: build_lib @mkdir -p $(INCDIR) @mkdir -p $(ALIDIR) $(INSTALL) -m 644 $(SOURCEDIR)/* $(INCDIR) $(INSTALL) -m 444 $(ALI_FILES) $(ALIDIR) install_static: $(INSTALL) -m 444 lib/$(A_LIBRARY) $(PREFIX)/lib install_dynamic: $(INSTALL) -m 444 lib/$(SO_LIBRARY) $(PREFIX)/lib @cd $(PREFIX)/lib && \ ln -sf $(SO_LIBRARY) libpcscada.so && \ ln -sf $(SO_LIBRARY) libpcscada.so.$(MAJOR) apidoc: @echo "Creating API doc for version $(VERSION) ..." @mkdir -p $(DOCDIR)/api @ls $(SOURCEDIR)/*.ads > pcscada.specs @adabrowse -c adabrowse.cfg -p -t -i -I src/ -f@pcscada.specs \ -o $(DOCDIR)/api/ @rm pcscada.specs doc: @$(MAKE) -C doc dist: distclean @echo -n "Creating release tarball '$(PCSCADA)' ($(VERSION)) ... " @mkdir -p $(DISTDIR) @cp -R * $(DISTDIR) @tar -C $(TMPDIR) -cjf $(TARBALL) $(PCSCADA) @rm -rf $(DISTDIR) @echo "DONE" .PHONY: apidoc dist doc itests utests libpcscada-0.7.1/examples/0000755000175000017500000000000011664137641014113 5ustar reetreetlibpcscada-0.7.1/examples/thin/0000755000175000017500000000000011664137641015055 5ustar reetreetlibpcscada-0.7.1/examples/thin/thin_example.adb0000644000175000017500000001627311664137641020213 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with Interfaces.C; with Interfaces.C.Strings; with PCSC.Thin; use PCSC.Thin; with PCSC.SCard.Utils; use PCSC; -- Thin-binding example procedure Thin_Example is pragma Linker_Options ("-lpcsclite"); package SCU renames SCard.Utils; use Interfaces.C; hContext : aliased SCARDCONTEXT; ret : DWORD; begin ret := SCardEstablishContext (dwScope => SCARD_SCOPE_SYSTEM, phContext => hContext'Access); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("context established"); else Ada.Text_IO.Put_Line ("could not establish context"); return; end if; ret := SCardIsValidContext (hContext => hContext); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("context is valid"); else Ada.Text_IO.Put_Line ("context not valid"); return; end if; declare dwReaders : aliased DWORD; mszReaders : LPSTR; hCard : aliased SCARDHANDLE; dwActiveProtocol : aliased DWORD; dwState : aliased DWORD; dwProtocol : aliased DWORD; dwAtrLen : aliased DWORD := MAX_ATR_SIZE; dwReaderLen : aliased DWORD; pbAtr : Byte_Array (1 .. MAX_ATR_SIZE); -- Modify Reader_Name according to your test setup Reader_Name : C.Strings.chars_ptr := C.Strings.New_String ("OmniKey CardMan 3121 00 00"); begin -- List readers ret := SCardListReaders (hContext => hContext, mszReaders => Interfaces.C.Strings.Null_Ptr, pcchReaders => dwReaders'Access); if not (ret = SCARD_S_SUCCESS) then Ada.Text_IO.Put_Line ("could not get list of readers"); return; end if; -- NULL termination is counted as well if dwReaders = 1 then Ada.Text_IO.Put_Line ("no readers found"); return; end if; mszReaders := C.Strings.To_Chars_Ptr (new C.char_array (C.size_t (1) .. C.size_t (dwReaders))); ret := SCardListReaders (hContext => hContext, mszReaders => mszReaders, pcchReaders => dwReaders'Access); if not (ret = SCARD_S_SUCCESS) then Ada.Text_IO.Put_Line ("could not get list of readers"); return; end if; Ada.Text_IO.Put_Line ("readers: " & Interfaces.C.Strings.Value (mszReaders)); -- Try to connect ret := SCardConnect (hContext => hContext, szReader => Reader_Name, dwShareMode => SCARD_SHARE_SHARED, dwPreferredProtocols => SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1, phCard => hCard'Access, pdwActiveProtocol => dwActiveProtocol'Access); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("connect ok"); -- Try to re-connect ret := SCardReconnect (hCard => hCard, dwShareMode => SCARD_SHARE_SHARED, dwPreferredProtocols => SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1, dwInitialization => SCARD_LEAVE_CARD, pdwActiveProtocol => dwActiveProtocol'Access); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("re-connect ok"); end if; else Ada.Text_IO.Put_Line ("connect to card failed"); return; end if; -- Get status SCardStatus (returnValue => ret, hCard => hCard, mszReaderNames => C.Strings.Null_Ptr, pcchReaderLen => dwReaderLen'Access, pdwState => dwState'Access, pdwProtocol => dwProtocol'Access, pbAtr => Byte_Array (pbAtr), pcbAtrLen => dwAtrLen'Access); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("card status ok"); Ada.Text_IO.Put_Line (" -- ATR len: " & DWORD'Image (dwAtrLen)); Ada.Text_IO.Put_Line (" -- ATR : " & String (SCU.To_Hex_String (Given => pbAtr, Len => 2 * Integer (dwAtrLen)))); Ada.Text_IO.Put_Line (" -- STATE : " & DWORD'Image (dwState)); Ada.Text_IO.Put_Line (" -- PROTO : " & DWORD'Image (dwProtocol)); else Ada.Text_IO.Put_Line ("get status failed"); return; end if; -- Begin transaction ret := SCardBeginTransaction (hCard => hCard); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("transaction start ok"); end if; declare pbRecvBuffer : Byte_Array (1 .. 10); pbSendBuffer : constant Byte_Array := (16#00#, 16#A4#, 16#00#, 16#00#, 16#02#, 16#3F#, 16#00#); pcbRecvLength : aliased DWORD := 10; pioRecvPCI : aliased Thin.SCARD_IO_REQUEST; begin -- Send arbitrary APDU to card SCardTransmit (returnValue => ret, hCard => hCard, pioSendPci => SCARD_PCI_T1'Access, pbSendBuffer => pbSendBuffer, cbSendLength => 7, pioRecvPci => pioRecvPCI'Access, pbRecvBuffer => pbRecvBuffer, pcbRecvLength => pcbRecvLength'Access); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("transmit send ok"); end if; Ada.Text_IO.Put_Line ("response from card: " & String (SCU.To_Hex_String (Given => pbRecvBuffer, Len => 2 * Integer (pcbRecvLength)))); end; -- End transaction ret := SCardEndTransaction (hCard => hCard, dwDisposition => SCARD_LEAVE_CARD); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("transaction end ok"); end if; -- Disconnect ret := SCardDisconnect (hCard => hCard, dwDisposition => SCARD_RESET_CARD); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("disconnect ok"); end if; -- Free memory C.Strings.Free (Reader_Name); end; ret := SCardReleaseContext (hContext => hContext); if ret = SCARD_S_SUCCESS then Ada.Text_IO.Put_Line ("context released"); end if; end Thin_Example; libpcscada-0.7.1/examples/cardd/0000755000175000017500000000000011664137641015170 5ustar reetreetlibpcscada-0.7.1/examples/cardd/reader_observer.adb0000644000175000017500000000332611664137641021015 0ustar reetreet-- -- Copyright (c) 2008-2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with PCSC.SCard.Utils; package body Reader_Observer is package Utils renames PCSC.SCard.Utils; ------------------------------------------------------------------------- procedure Notify (O : Instance; Condition : SCard.Reader_Condition) is begin Ada.Text_IO.Put_Line ("[observer (" & Utils.To_String (States => O.States) & ") ]"); Ada.Text_IO.Put_Line ("Reader : " & Utils.To_String (Condition.Name)); Ada.Text_IO.Put_Line ("State : " & Utils.To_String (Condition.Current_State)); if Condition.Current_State.Is_In (State => SCard.S_Reader_Present) then Ada.Text_IO.Put_Line ("ATR : " & Utils.To_Hex_String (Given => Condition.Card_ATR)); end if; Ada.Text_IO.New_Line; end Notify; end Reader_Observer; libpcscada-0.7.1/examples/cardd/reader_observer.ads0000644000175000017500000000233411664137641021034 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- -- -- Simple reader observer example. -- -- with PCSC.SCard; with PCSC.SCard.Monitor; use PCSC; package Reader_Observer is type Instance is new SCard.Monitor.Observer with null record; overriding procedure Notify (O : Instance; Condition : SCard.Reader_Condition); -- Implementation of a reader monitor observer. end Reader_Observer; libpcscada-0.7.1/examples/cardd/cardd.adb0000644000175000017500000000465611664137641016730 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with Reader_Observer; with PCSC.Version; with PCSC.SCard.Utils; with PCSC.SCard.Monitor; use PCSC; procedure Cardd is pragma Linker_Options ("-lpcsclite"); package SCU renames SCard.Utils; Context : aliased SCard.Context; begin Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("** PCSC/Ada card daemon [version " & PCSC.Version.Version_String & "] **"); Ada.Text_IO.New_Line; -- Establish context begin SCU.Action_Info (Text => "Establishing context"); SCard.Establish_Context (Context => Context, Scope => SCard.Scope_System); SCU.Action_Result (Result => SCard.Get_Return_Code); exception when SCard_Error => SCU.Action_Result (Result => "FAILED: " & SCard.Get_Return_Code); return; when others => SCU.Action_Result (Result => "Unknown error."); return; end; Ada.Text_IO.New_Line; declare Monitor : SCard.Monitor.Reader_Monitor; Observer : aliased Reader_Observer.Instance; begin -- Add all the states we are interested in Observer.States.Add (State => SCard.S_Reader_Present); Observer.States.Add (State => SCard.S_Reader_Empty); Observer.States.Add (State => SCard.S_Reader_Unavailable); Ada.Text_IO.Put_Line ("Starting reader monitoring task ... "); Monitor.Init (Context => Context'Unchecked_Access); -- Register our observer to the reader monitoring task Monitor.Register (O => Observer); -- Start the monitoring task Monitor.Start; end; end Cardd; libpcscada-0.7.1/examples/pinverify/0000755000175000017500000000000011664137641016126 5ustar reetreetlibpcscada-0.7.1/examples/pinverify/pinpad.adb0000644000175000017500000001214011664137641020047 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with PCSC.Version; with PCSC.SCard.Utils; use PCSC; -- Test SPE (secure PIN entry) PIN verification by using the readers pinpad. -- First, the Supports_SPE() function of the thick binding is used to test if -- the reader supporst this operation. If the reader does support SPE, the -- user is asked to enter the smart card PIN at the card reader. procedure Pinpad is pragma Linker_Options ("-lpcsclite"); package SCU renames SCard.Utils; Context : SCard.Context; Card : SCard.Card; Readers : SCard.Reader_ID_Set; Card_States : SCard.Card_States_Set; Card_Proto : SCard.Proto := SCard.Proto_Undefined; Card_ATR : SCard.ATR; begin Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("** PCSC/Ada PIN verfification example [version " & PCSC.Version.Version_String & "] **"); Ada.Text_IO.New_Line; -- Establish context SCU.Action_Info (Text => "Establishing context"); SCard.Establish_Context (Context => Context, Scope => SCard.Scope_System); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Test for valid context SCU.Action_Info (Text => "Verifying context"); if not SCard.Is_Valid (Context => Context) then SCU.Action_Result (Result => "FAILED : " & SCard.Get_Return_Code); end if; SCU.Action_Result (Result => SCard.Get_Return_Code); -- Get reader list SCU.Action_Info (Text => "Asking for readers"); Readers := SCard.List_Readers (Context => Context); SCU.Action_Result (Result => SCard.Get_Return_Code); if Readers.Empty then Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("No Readers found!"); SCard.Release_Context (Context => Context); return; end if; Ada.Text_IO.Put_Line ("> Readers found : "); SCU.For_Every_Reader (Readers => Readers, Call => SCU.Print_ReaderID'Access); -- Connect to first reader SCU.Action_Info (Text => "Connecting to first reader"); SCard.Connect (Context => Context, Card => Card, Reader => Readers.First_Item, Mode => SCard.Share_Direct); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Get card status, return if no card is present SCU.Action_Info (Text => "Testing card status"); SCard.Status (Card => Card, State => Card_States, Proto => Card_Proto, Atr => Card_ATR); SCU.Action_Result (Result => SCard.Get_Return_Code); if Card_States.Is_In (State => SCard.S_Card_Absent) then Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("No card inserted!"); return; end if; -- Test if reader supports PIN verification declare Recv_Buffer : SCard.Byte_Set (1 .. 2); Supported : Boolean := False; begin SCU.Action_Info (Text => "Testing for verify feature"); SCard.SPE_Init (Card => Card, Result => Supported); if not Supported then SCU.Action_Result (Result => "Not supported by reader."); return; end if; SCU.Action_Result (Result => "Supported by reader."); -- Execute SPE operation SCU.Action_Info (Text => "Enter PIN on pinpad"); SCard.SPE_Exec (Card => Card, Result => Recv_Buffer); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Display return code SCU.Action_Info (Text => "Return code from reader"); SCU.Action_Result (Result => SCU.To_Hex_String (Given => Recv_Buffer)); end; -- Disconnect from first reader SCU.Action_Info (Text => "Disconnecting"); SCard.Disconnect (Card => Card, Action => SCard.Unpower_Card); SCU.Action_Result (Result => SCard.Get_Return_Code); -- Release context SCU.Action_Info (Text => "Releasing context"); SCard.Release_Context (Context => Context); SCU.Action_Result (Result => SCard.Get_Return_Code); Ada.Text_IO.New_Line; Ada.Text_IO.Put_Line ("DONE!"); Ada.Text_IO.New_Line; exception when others => SCU.Action_Result (Result => "FAILED: " & SCard.Get_Return_Code); if SCard.Is_Valid (Context => Context) then SCard.Release_Context (Context => Context); end if; raise; end Pinpad; libpcscada-0.7.1/examples/ifd/0000755000175000017500000000000011664137641014655 5ustar reetreetlibpcscada-0.7.1/examples/ifd/ifd.adb0000644000175000017500000001575011664137641016077 0ustar reetreet-- -- Copyright (c) 2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with Ada.Text_IO; with PCSC.Thin.Reader; package body IFD is Fake_ATR : constant PCSC.Thin.ATR := (16#3B#, 16#FA#, 16#13#, 16#00#, 16#FF#, 16#81#, 16#31#, 16#80#, 16#45#, 16#00#, 16#31#, 16#C1#, 16#73#, 16#C0#, 16#01#, 16#00#, 16#00#, 16#90#, 16#00#, 16#B1#, others => 0); -- Fake OpenPGP ATR ------------------------------------------------------------------------- function IFDHCloseChannel (Lun : DWORD) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun); begin Ada.Text_IO.Put_Line ("Ada:IFDHCloseChannel"); return IFDHandler.IFD_SUCCESS; end IFDHCloseChannel; ------------------------------------------------------------------------- function IFDHControl (Lun : DWORD; TxBuffer : Value_Access; TxLength : DWORD; RxBuffer : Value_Access; RxLength : PDWORD) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, TxBuffer, TxLength, RxBuffer, RxLength); begin Ada.Text_IO.Put_Line ("Ada:IFDHControl"); return IFDHandler.IFD_SUCCESS; end IFDHControl; ------------------------------------------------------------------------- function IFDHCreateChannel (Lun : DWORD; Channel : DWORD) return PCSC.Thin.IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, Channel); begin Ada.Text_IO.Put_Line ("Ada:IFDHCreateChannel"); return IFDHandler.IFD_SUCCESS; end IFDHCreateChannel; ------------------------------------------------------------------------- function IFDHCreateChannelByName (Lun : DWORD; DeviceName : LPSTR) return PCSC.Thin.IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, DeviceName); begin Ada.Text_IO.Put_Line ("Ada:IFDHCreateChannelByName"); return IFDHandler.IFD_SUCCESS; end IFDHCreateChannelByName; ------------------------------------------------------------------------- procedure IFDHGetCapabilities (Result : out DWORD; Lun : DWORD; Tag : DWORD; Length : PDWORD; Value : Value_Access) is pragma Unreferenced (Lun); begin Ada.Text_IO.Put_Line ("Ada:IFDHGetCapabilities"); if Length = null then Result := IFDHandler.IFD_ERROR_TAG; return; end if; Result := IFDHandler.IFD_SUCCESS; if Value = null then -- Client wants to know the attribute's data length. Fake it. Length.all := MAX_ATR_SIZE; return; end if; case Tag is when IFDHandler.TAG_IFD_ATR => Ada.Text_IO.Put_Line ("Ada:IFDHGetCapabilities:TAG_IFD_ATR"); when IFDHandler.TAG_IFD_SLOTS_NUMBER => Ada.Text_IO.Put_Line ("Ada:IFDHGetCapabilities:TAG_IFD_SLOTS_NUMBER"); when IFDHandler.TAG_IFD_SIMULTANEOUS_ACCESS => Ada.Text_IO.Put_Line ("Ada:FDHGetCapabilities:TAG_IFD_SIMULTANEOUS_ACCESS"); when Reader.SCARD_ATTR_VENDOR_NAME => Ada.Text_IO.Put_Line ("Ada:FDHGetCapabilities:SCARD_ATTR_VENDOR_NAME"); Value.all := Value_Array'(16#41#, 16#64#, 16#61#, others => 0); Length.all := 3; when Reader.SCARD_ATTR_ATR_STRING => Ada.Text_IO.Put_Line ("Ada:FDHGetCapabilities:SCARD_ATTR_ATR_STRING"); Value.all := Fake_ATR; Length.all := 20; when Reader.SCARD_ATTR_MAXINPUT => Ada.Text_IO.Put_Line ("Ada:FDHGetCapabilities:SCARD_ATTR_MAXINPUT"); Value.all := Value_Array'(16#12#, 16#24#, others => 0); Length.all := 2; when others => Ada.Text_IO.Put_Line ("Ada:FDHGetCapabilities:UNHANDLED_TAG:" & Tag'Img); Result := IFDHandler.IFD_ERROR_TAG; end case; end IFDHGetCapabilities; ------------------------------------------------------------------------- function IFDHICCPresence (Lun : DWORD) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun); begin return IFDHandler.IFD_SUCCESS; end IFDHICCPresence; ------------------------------------------------------------------------- procedure IFDHPowerICC (Result : out IFDHandler.RESPONSECODE; Lun : DWORD; Action : DWORD; Atr : ATR_Access; AtrLength : PDWORD) is pragma Unreferenced (Lun, Action); begin Ada.Text_IO.Put_Line ("Ada:IFDHPowerICC"); -- Return fake OpenPGP ATR Atr.all := Fake_ATR; AtrLength.all := 20; Result := IFDHandler.IFD_SUCCESS; end IFDHPowerICC; ------------------------------------------------------------------------- function IFDHSetCapabilities (Lun : DWORD; Tag : DWORD; Length : DWORD; Value : Value_Access) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, Tag, Length, Value); begin Ada.Text_IO.Put_Line ("Ada:IFDHSetCapabilities"); return IFDHandler.IFD_SUCCESS; end IFDHSetCapabilities; ------------------------------------------------------------------------- function IFDHSetProtocolParameters (Lun : DWORD; Protocol : DWORD; Flags : UCHAR; PTS1 : UCHAR; PTS2 : UCHAR; PTS3 : UCHAR) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, Protocol, Flags, PTS1, PTS2, PTS3); begin Ada.Text_IO.Put_Line ("Ada:IFDHSetProtocolParameters"); return IFDHandler.IFD_SUCCESS; end IFDHSetProtocolParameters; ------------------------------------------------------------------------- function IFDHTransmitToICC (Lun : DWORD; SendPci : IFDHandler.SCARD_IO_HEADER; TxBuffer : Value_Access; TxLength : DWORD; RxBuffer : Value_Access; RxLength : PDWORD; RecvPci : IFDHandler.PSCARD_IO_HEADER) return IFDHandler.RESPONSECODE is pragma Unreferenced (Lun, SendPci, TxBuffer, TxLength, RxBuffer, RxLength, RecvPci); begin Ada.Text_IO.Put_Line ("Ada:IFDHTransmitToICC"); return IFDHandler.IFD_SUCCESS; end IFDHTransmitToICC; end IFD; libpcscada-0.7.1/examples/ifd/ifd.gpr0000644000175000017500000000270211664137641016132 0ustar reetreet-- -- Copyright (c) 2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with "../../pcscada_common"; project IFD is for Source_Dirs use (".", "../../src"); for Object_Dir use "obj"; for Library_Name use "ifdada"; for Library_Dir use "lib"; for Library_Kind use external ("LIBRARY_KIND", "dynamic"); for Library_Interface use ("IFD", "PCSC", "PCSC.Thin", "PCSC.Thin.IFDHandler"); package Compiler is for Default_Switches ("ada") use PCSCAda_Common.Compiler_Switches; end Compiler; package Binder is for Default_Switches ("ada") use ("-E"); end Binder; end IFD; libpcscada-0.7.1/examples/ifd/ifd.ads0000644000175000017500000001066411664137641016117 0ustar reetreet-- -- Copyright (c) 2010, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with PCSC.Thin.IFDHandler; package IFD is use PCSC.Thin; subtype Value_Array is Byte_Array (0 .. MAX_ATR_SIZE); -- Transfer data, use max ATR size as upper constraint for now type Value_Access is access Value_Array; -- Access to transfer data array function IFDHCloseChannel (Lun : DWORD) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHCloseChannel, External_Name => "IFDHCloseChannel"); function IFDHControl (Lun : DWORD; TxBuffer : Value_Access; TxLength : DWORD; RxBuffer : Value_Access; RxLength : PDWORD) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHControl, External_Name => "IFDHControl"); function IFDHCreateChannel (Lun : DWORD; Channel : DWORD) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHCreateChannel, External_Name => "IFDHCreateChannel"); function IFDHCreateChannelByName (Lun : DWORD; DeviceName : LPSTR) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHCreateChannelByName, External_Name => "IFDHCreateChannelByName"); procedure IFDHGetCapabilities (Result : out DWORD; Lun : DWORD; Tag : DWORD; Length : PDWORD; Value : Value_Access); pragma Export (Convention => C, Entity => IFDHGetCapabilities, External_Name => "IFDHGetCapabilities"); pragma Export_Valued_Procedure (Internal => IFDHGetCapabilities, External => "IFDHGetCapabilities"); function IFDHICCPresence (Lun : DWORD) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHICCPresence, External_Name => "IFDHICCPresence"); procedure IFDHPowerICC (Result : out IFDHandler.RESPONSECODE; Lun : DWORD; Action : DWORD; Atr : ATR_Access; AtrLength : PDWORD); pragma Export (Convention => C, Entity => IFDHPowerICC, External_Name => "IFDHPowerICC"); pragma Export_Valued_Procedure (Internal => IFDHPowerICC, External => "IFDHPowerICC"); function IFDHSetCapabilities (Lun : DWORD; Tag : DWORD; Length : DWORD; Value : Value_Access) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHSetCapabilities, External_Name => "IFDHSetCapabilities"); function IFDHSetProtocolParameters (Lun : DWORD; Protocol : DWORD; Flags : UCHAR; PTS1 : UCHAR; PTS2 : UCHAR; PTS3 : UCHAR) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHSetProtocolParameters, External_Name => "IFDHSetProtocolParameters"); function IFDHTransmitToICC (Lun : DWORD; SendPci : IFDHandler.SCARD_IO_HEADER; TxBuffer : Value_Access; TxLength : DWORD; RxBuffer : Value_Access; RxLength : PDWORD; RecvPci : IFDHandler.PSCARD_IO_HEADER) return IFDHandler.RESPONSECODE; pragma Export (Convention => C, Entity => IFDHTransmitToICC, External_Name => "IFDHTransmitToICC"); end IFD; libpcscada-0.7.1/examples/sample/0000755000175000017500000000000011664137641015374 5ustar reetreetlibpcscada-0.7.1/examples/sample/sample.adb0000644000175000017500000000254511664137641017333 0ustar reetreetwith PCSC.SCard; use PCSC; procedure Sample is pragma Linker_Options ("-lpcsclite"); Context : SCard.Context; -- PC/SC context Card : SCard.Card; -- Card handle Readers : SCard.Reader_ID_Set; -- Set of readers begin -- Establish context SCard.Establish_Context (Context => Context, Scope => SCard.Scope_System); -- List readers Readers := SCard.List_Readers (Context => Context); -- Connect to first reader SCard.Connect (Context => Context, Card => Card, Reader => Readers.First_Item, Mode => SCard.Share_Shared); -- Send APDU to card declare Recv_Buffer : SCard.Byte_Set (1 .. 10); Send_Buffer : constant SCard.Byte_Set := (16#00#, 16#A4#, 16#00#, 16#00#, 16#02#, 16#3F#, 16#00#); Recv_Length : Natural := 0; Recv_PCI : SCard.IO_Request; begin SCard.Transmit (Card => Card, Send_Buffer => Send_Buffer, Recv_Pci => Recv_PCI, Recv_Buffer => Recv_Buffer, Recv_Len => Recv_Length); end; -- Disconnect SCard.Disconnect (Card => Card, Action => SCard.Reset_Card); -- Release context SCard.Release_Context (Context => Context); end Sample; libpcscada-0.7.1/pcscada_examples.gpr0000644000175000017500000000264511664137641016312 0ustar reetreet-- -- Copyright (c) 2008, -- Reto Buerki -- -- This file is part of PCSC/Ada. -- -- PCSC/Ada is free software; you can redistribute it and/or modify -- it under the terms of the GNU Lesser General Public License as published -- by the Free Software Foundation; either version 2.1 of the License, or -- (at your option) any later version. -- -- PCSC/Ada is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public License -- along with PCSC/Ada; if not, write to the Free Software -- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, -- MA 02110-1301 USA -- with "pcscada_common"; project PCSCAda_Examples is for Object_Dir use "obj/examples"; for Source_Dirs use ("src", "examples/cardd", "examples/pinverify", "examples/thin", "examples/sample"); for Main use ("cardd.adb", "pinpad.adb", "sample.adb", "thin_example.adb"); package Compiler is for Default_Switches ("ada") use PCSCAda_Common.Compiler_Switches; end Compiler; package Binder is for Default_Switches ("ada") use ("-E"); end Binder; end PCSCAda_Examples; libpcscada-0.7.1/LICENSE0000644000175000017500000006347111664137641013315 0ustar reetreet GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libpcscada-0.7.1/adabrowse.cfg0000644000175000017500000000045711664137641014733 0ustar reetreet# AdaBrowse configuration file for PCSC/Ada index_xref = TARGET="main" User_Tag.I_START_ =
    User_Tag.I_INIT_ =
    User_Tag.I_END_ =
    User_Tag.PURPOSE.Before = Purpose: User_Tag.PURPOSE.After = # EOF