diff --git a/src/error.rs b/src/error.rs
index c68f0df..e0fa1e6 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,14 +1,33 @@
 use std::io;
 use std::fmt;
-use hex::FromHexError;
 
 #[derive(Debug)]
 pub enum Error {
     IO(io::Error),
     Boxed(Box<dyn std::error::Error>),
+    Simple(simple_error::SimpleError),
     BlockModeError(block_modes::BlockModeError),
     InvalidKeyIvLength(block_modes::InvalidKeyIvLength),
-    FromHexError(hex::FromHexError)
+    FromHexError(hex::FromHexError),
+    PadError(block_modes::block_padding::PadError),
+    InvalidStatusWord,
+    IllegalCommandCode,
+    IntegrityError,
+    NoSuchKey,
+    LengthError,
+    PermissionDenied,
+    ParameterError,
+    AuthenticationDelay,
+    AuthenticationError,
+    BoundaryError,
+    CommandAborted,
+    DuplicateError,
+    FileNotFound,
+    InvalidApplicationID,
+    InvalidAPDUResponse,
+    InvalidKeyID,
+    InvalidPICCChallenge,
+    InvalidFileID,
 }
 
 impl fmt::Display for Error {
@@ -16,19 +35,79 @@ impl fmt::Display for Error {
         match self {
             Error::IO(e) => {
                 write!(f, "IO Error: {}", e)
-            },
+            }
             Error::Boxed(e) => {
                 write!(f, "{}", e)
-            },
+            }
+            Error::Simple(e) => {
+                write!(f, "Generic Error: {}", e)
+            }
             Error::BlockModeError(e) => {
                 write!(f, "CBC Error: {}", e)
-            },
+            }
             Error::InvalidKeyIvLength(e) => {
                 write!(f, "CBC InvalidKeyIvLength Error: {}", e)
             }
             Error::FromHexError(e) => {
                 write!(f, "Hex conversion Error: {}", e)
             }
+            Error::PadError(e) => {
+                write!(f, "Padding to blocksize failed: {:#?}", e)
+            }
+            Error::InvalidStatusWord => {
+                write!(f, "Invalid APDU Statusword")
+            }
+            Error::IllegalCommandCode => {
+                write!(f, "SW2: Command code not supported.")
+            }
+            Error::IntegrityError => {
+                write!(f, "SW2: CRC or MAC does not match data. Paddingbytes not valid.")
+            }
+            Error::NoSuchKey => {
+                write!(f, "SW2: Invalid key number specified.")
+            }
+            Error::LengthError => {
+                write!(f, "SW2: Length of command string invalid.")
+            }
+            Error::PermissionDenied => {
+                write!(f, "SW2: Current configuration / status does not allow the requested command.")
+            }
+            Error::ParameterError => {
+                write!(f, "SW2: Value of the parameter(s) invalid.")
+            }
+            Error::AuthenticationDelay => {
+                write!(f, "SW2: Currently not allowed to authenticate. Keeptrying until full delay is spent.")
+            }
+            Error::AuthenticationError => {
+                write!(f, "SW2: Current authentication status does not allow the requested command.")
+            }
+            Error::BoundaryError => {
+                write!(f, "SW2: Attempt to read/write data from/to beyond the file’s/record’s limits. Attempt to exceed the limits of a value file.")
+            }
+            Error::CommandAborted => {
+                write!(f, "SW2: Previous Command was not fully completed.Not all Frames were requested or provided by the PCD.")
+            }
+            Error::DuplicateError => {
+                write!(f, "SW2: Creation of file/application failed because file/application with same number already exists")
+            }
+            Error::FileNotFound => {
+                write!(f, "SW2: Specified file number does not exist.")
+            }
+            Error::InvalidApplicationID => {
+                write!(f, "Application ID was larger then 24 bit")
+            }
+            Error::InvalidAPDUResponse => {
+                write!(f, "Got malformed APDUResponse")
+            }
+            Error::InvalidKeyID => {
+                write!(f, "Invalid KeyID: Was larger then 0x0E")
+            }
+            Error::InvalidPICCChallenge => {
+                write!(f, "Authentication failed, PICC Challenge is invalid.")
+            }
+            Error::InvalidFileID => {
+                write!(f, "Invalid FileID: Was larger then 0x20")
+            }
         }
     }
 }
@@ -39,6 +118,10 @@ impl From<io::Error> for Error {
     }
 }
 
+impl From<simple_error::SimpleError> for Error {
+    fn from(e: simple_error::SimpleError) -> Error { Error::Simple(e) }
+}
+
 impl From<block_modes::BlockModeError> for Error {
     fn from(e: block_modes::BlockModeError) -> Error {
         Error::BlockModeError(e)
@@ -52,7 +135,11 @@ impl From<block_modes::InvalidKeyIvLength> for Error {
 }
 
 impl From<hex::FromHexError> for Error {
-    fn from(e: hex::FromHexError) -> Error { Error::FromHexError(e)}
+    fn from(e: hex::FromHexError) -> Error { Error::FromHexError(e) }
+}
+
+impl From<block_modes::block_padding::PadError> for Error {
+    fn from(e: block_modes::block_padding::PadError) -> Error { Error::PadError(e) }
 }
 
 pub(crate) type Result<T> = std::result::Result<T, Error>;
diff --git a/src/iso7816_4/apducommand.rs b/src/iso7816_4/apducommand.rs
new file mode 100644
index 0000000..0c1f861
--- /dev/null
+++ b/src/iso7816_4/apducommand.rs
@@ -0,0 +1,261 @@
+use std::fmt;
+use std::fmt::Formatter;
+
+#[repr(u8)]
+#[derive(Eq, PartialEq, Hash, Debug)]
+pub enum IsoCase {
+    /// <summary>No command data. No response data.</summary>
+        /// <remarks>
+        ///     <list type="bullet">
+        ///         <item><description>lc is valued to 0.</description></item>
+        ///         <item><description>le is valued to 0.</description></item>
+        ///         <item><description>No data byte is present.</description></item>
+        ///     </list>
+        /// </remarks>
+    Case1 = 0,
+
+    /// <summary>No command data. Expected response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued to 0.</description></item>
+    ///         <item><description>le is valued from 1 to 256.</description></item>
+    ///         <item><description>No data byte is present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case2Short = 1,
+
+    /// <summary>Command data. No response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued from 1 to 255.</description></item>
+    ///         <item><description>le is valued to 0.</description></item>
+    ///         <item><description>lc data bytes are present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case3Short = 2,
+
+    /// <summary>Command data. Expected response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued from 1 to 255.</description></item>
+    ///         <item><description>le is valued from 1 to 256.</description></item>
+    ///         <item><description>lc data bytes are present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case4Short = 3,
+
+    /// <summary>No command data. Expected response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued to 0.</description></item>
+    ///         <item><description>le is valued from 1 to 65536.</description></item>
+    ///         <item><description>No data byte is present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case2Extended = 4,
+
+    /// <summary>Command data. No response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued from 1 to 65536.</description></item>
+    ///         <item><description>le is valued to 0.</description></item>
+    ///         <item><description>lc data bytes are present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case3Extended = 5,
+
+    /// <summary>Command data. Expected response data.</summary>
+    /// <remarks>
+    ///     <list type="bullet">
+    ///         <item><description>lc is valued from 1 to 65535.</description></item>
+    ///         <item><description>le is valued from 1 to 65536.</description></item>
+    ///         <item><description>lc data bytes are present.</description></item>
+    ///     </list>
+    /// </remarks>
+    Case4Extended = 6,
+}
+
+impl Default for IsoCase {
+    fn default() -> Self { IsoCase::Case1 }
+}
+
+#[repr(u8)]
+#[derive(Eq, PartialEq, Hash, Debug)]
+pub enum SCardProtocol {
+    /// <summary>
+    /// protocol not defined.
+    /// </summary>
+    Unset = 0x0000,
+
+    /// <summary>T=0 active protocol.</summary>
+    T0 = 0x0001,
+
+    /// <summary>T=1 active protocol.</summary>
+    T1 = 0x0002,
+
+    /// <summary>Raw active protocol. Use with memory type cards.</summary>
+    Raw = 0x0004,
+
+    /// <summary>T=15 protocol.</summary>
+    T15 = 0x0008,
+
+    /// <summary>(<see cref="SCardProtocol.T0" /> | <see cref="SCardProtocol.T1" />). IFD (Interface device) determines protocol.</summary>
+    Any = (0x0001 | 0x0002),
+}
+
+impl Default for SCardProtocol {
+    fn default() -> Self { SCardProtocol::Unset }
+}
+
+#[derive(Eq, PartialEq, Hash, Debug, Default)]
+pub struct APDUCommand {
+    pub case: IsoCase,
+    pub protocol: SCardProtocol,
+    pub cla: u8,
+    pub ins: u8,
+    pub p1: u8,
+    pub p2: u8,
+    pub data: Option<Vec<u8>>,
+    pub lc: i32,
+    pub le: i32,
+}
+//FIXME: Do we want pub fields or constructor?
+// We want pub fields! + constructor?
+
+// impl APDUCommand {
+//     pub fn new(case: IsoCase) -> Self {
+//         APDUCommand { case, protocol: (), cla: (), ins: (), p1: (), p2: (), data: (), lc: (), le: () }
+//     }
+// }
+
+impl fmt::Display for APDUCommand {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        match self.case {
+            IsoCase::Case1 => {
+                write!(f, "(CASE: 1) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X}", self.cla, self.ins, self.p1, self.p2)
+            }
+            IsoCase::Case2Short | IsoCase::Case2Extended => {
+                write!(f, "(CASE: 2) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LE: {:#X}", self.cla, self.ins, self.p1, self.p2, self.le)
+            }
+            IsoCase::Case3Short | IsoCase::Case3Extended => {
+                write!(f, "(CASE: 3) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LC: {:#X} | data: [ ", self.cla, self.ins, self.p1, self.p2, self.lc)?;
+                for b in self.data.as_ref().unwrap() {
+                    write!(f, "{:#X} ", b)?;
+                }
+                write!(f, "]")
+            }
+            IsoCase::Case4Short | IsoCase::Case4Extended => {
+                write!(f, "(CASE: 4) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LC: {:#X} | data: [ ", self.cla, self.ins, self.p1, self.p2, self.lc)?;
+                for b in self.data.as_ref().unwrap() {
+                    write!(f, "{:#X} ", b)?;
+                }
+                write!(f, "] | LE: {:#X}", self.le)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::iso7816_4::apducommand::{APDUCommand, SCardProtocol, IsoCase};
+
+    #[test]
+    fn compare() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case4Short,
+            protocol: SCardProtocol::Unset,
+            cla: 0x90,
+            ins: 0xAA,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        let command2 = APDUCommand{
+            case: IsoCase::Case4Short,
+            protocol: SCardProtocol::Unset,
+            cla: 0x90,
+            ins: 0xAA,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        assert_eq!(command1, command2);
+    }
+
+    #[test]
+    fn compare_diff() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case4Short,
+            protocol: SCardProtocol::Unset,
+            cla: 0x90,
+            ins: 0xAA,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        let command2 = APDUCommand{
+            case: IsoCase::Case4Short,
+            protocol: SCardProtocol::Unset,
+            cla: 0x90,
+            ins: 0x1A,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        assert_ne!(command1, command2);
+    }
+
+    #[test]
+    fn to_string_case1() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case1,
+            cla: 0x90,
+            ins: 0x1A,
+            ..Default::default()
+        };
+
+        println!("{}", command1.to_string());
+        assert_eq!("(CASE: 1) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0", command1.to_string());
+    }
+
+    #[test]
+    fn to_string_case2() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case2Short,
+            cla: 0x90,
+            ins: 0x1A,
+            ..Default::default()
+        };
+
+        println!("{}", command1.to_string());
+        assert_eq!("(CASE: 2) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LE: 0x0", command1.to_string());
+    }
+
+    #[test]
+    fn to_string_case3() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case3Short,
+            cla: 0x90,
+            ins: 0x1A,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        println!("{}", command1.to_string());
+        assert_eq!("(CASE: 3) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LC: 0x0 | data: [ 0x1 0x2 0x3 ]", command1.to_string());
+    }
+
+    #[test]
+    fn to_string_case4() {
+        let command1 = APDUCommand{
+            case: IsoCase::Case4Short,
+            cla: 0x90,
+            ins: 0x1A,
+            data: Some(vec![0x01, 0x02, 0x03]),
+            ..Default::default()
+        };
+
+        println!("{}", command1.to_string());
+        assert_eq!("(CASE: 4) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LC: 0x0 | data: [ 0x1 0x2 0x3 ] | LE: 0x0", command1.to_string());
+    }
+}
\ No newline at end of file
diff --git a/src/iso7816_4/apduresponse.rs b/src/iso7816_4/apduresponse.rs
new file mode 100644
index 0000000..38cbc37
--- /dev/null
+++ b/src/iso7816_4/apduresponse.rs
@@ -0,0 +1,100 @@
+use crate::iso7816_4::apdustatuswords::{APDUStatusWord, APDUStatusWord2};
+use crate::error::{Result};
+use num_traits::FromPrimitive;
+use crate::error::Error::{InvalidStatusWord, IllegalCommandCode, IntegrityError, NoSuchKey, LengthError, PermissionDenied, ParameterError, AuthenticationDelay, AuthenticationError, BoundaryError, CommandAborted, DuplicateError, FileNotFound};
+use std::fmt;
+
+#[derive(Eq, PartialEq, Hash, Debug)]
+pub struct APDUResponse {
+    pub body: Vec<u8>,
+    pub sw1: u8,
+    pub sw2: u8,
+}
+
+impl APDUResponse {
+    pub fn body(&self) -> &Vec<u8> {
+        &self.body
+    }
+}
+
+impl From<APDUResponse> for Vec<u8> {
+    fn from(resp: APDUResponse) -> Self {
+        let mut v: Vec<u8> = vec![];
+        v.extend(resp.body);
+        v.push(resp.sw1);
+        v.push(resp.sw2);
+        v
+    }
+}
+
+impl fmt::Display for APDUResponse {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.body.is_empty() {
+            true => {
+                write!(f, "SW1: {:#X} | SW2: 0x{:#X}", self.sw1, self.sw2)
+            },
+            false => {
+                write!(f, "SW1: {:#X} | SW2: {:#X} | Body: {:#X?}", self.sw1, self.sw2, self.body)
+            }
+        }
+    }
+}
+
+impl APDUResponse {
+    pub fn new(raw: &[u8]) -> Self {
+        APDUResponse {
+            body: raw[..raw.len() - 1].to_vec(),
+            sw1: raw[raw.len() - 2],
+            sw2: raw[raw.len() - 3]
+        }
+    }
+
+    pub fn get_statusword(&self) -> Result<APDUStatusWord> {
+        match self.sw1 {
+            0x61 => Ok(APDUStatusWord::DataReady),
+            0x62 => Ok(APDUStatusWord::StorageNotChanged),
+            0x63 => {
+                if (self.sw2 & 0xF0) == 0xC0 { Ok(APDUStatusWord::CounterReached) } else { Ok(APDUStatusWord::StorageChanged) }
+            },
+            0x64 => Ok(APDUStatusWord::ExecutionErrorWithoutChange),
+            0x65 => Ok(APDUStatusWord::ExecutionErrorWithChange),
+            0x6C => Ok(APDUStatusWord::InvalidLe),
+            _ => FromPrimitive::from_u16(((self.sw1 as u16) << 8) | self.sw2 as u16).ok_or(InvalidStatusWord)
+        }
+    }
+
+    pub fn get_data_length(&self) -> u8 {
+        self.sw2
+    }
+
+    pub fn get_counter(&self) -> u8 {
+        self.sw2 & 0x0F
+    }
+
+    pub fn get_correct_le(&self) -> u8 {
+        self.sw2
+    }
+
+    pub fn check(&self) -> Result<()> {
+        if self.sw1 == 0x91 {
+            return match FromPrimitive::from_u8(self.sw2) {
+                Some(APDUStatusWord2::OperationOk) => { Ok(()) }
+                Some(APDUStatusWord2::NoChanges) => { Ok(()) }
+                Some(APDUStatusWord2::IllegalCommandCode) => {Err(IllegalCommandCode)}
+                Some(APDUStatusWord2::IntegrityError) => {Err(IntegrityError)}
+                Some(APDUStatusWord2::NoSuchKey) => {Err(NoSuchKey)}
+                Some(APDUStatusWord2::LengthError) => {Err(LengthError)}
+                Some(APDUStatusWord2::PermissionDenied) => {Err(PermissionDenied)}
+                Some(APDUStatusWord2::ParameterError) => {Err(ParameterError)}
+                Some(APDUStatusWord2::AuthenticationDelay) => {Err(AuthenticationDelay)}
+                Some(APDUStatusWord2::AuthenticationError) => {Err(AuthenticationError)}
+                Some(APDUStatusWord2::AdditionalFrame) => {Ok(())}
+                Some(APDUStatusWord2::BoundaryError) => {Err(BoundaryError)}
+                Some(APDUStatusWord2::CommandAborted) => {Err(CommandAborted)}
+                Some(APDUStatusWord2::DuplicateError) => {Err(DuplicateError)}
+                Some(APDUStatusWord2::FileNotFound) => {Err(FileNotFound)}
+                None => { Err(InvalidStatusWord)}
+            }
+        } else { Err(InvalidStatusWord) }
+    }
+}
\ No newline at end of file
diff --git a/src/iso7816_4/apdustatuswords.rs b/src/iso7816_4/apdustatuswords.rs
new file mode 100644
index 0000000..d2c627f
--- /dev/null
+++ b/src/iso7816_4/apdustatuswords.rs
@@ -0,0 +1,153 @@
+use num_derive::FromPrimitive;
+
+#[derive(FromPrimitive)]
+#[repr(u16)]
+pub enum APDUStatusWord {
+    /// Kommando erfolgreich ausgefhrt. xx Datenbytes knnen mit dem GET RESPONSE-Kommando abgeholt werden.	Statuswort zur Steuerung des T=0-Protokolls
+    DataReady = 0x6100,
+
+    /// Die zurckgegebenen Daten knnen fehlerhaft sein.
+    FaultyData = 0x6281,
+
+    /// Da das Dateiende vorher erreicht wurde, konnten nur weniger als Le Bytes gelesen werden.
+    UnexpectedEndOfFile = 0x6282,
+
+    /// Die ausgewhlte Datei ist gesperrt (englisch invalidated, wrtlich ungltig).
+    InvalidatedFile = 0x6283,
+
+    /// Die File Control Information (FCI) ist inkonform zu ISO 7816-4.
+    FciNotConform = 0x6284,
+
+    /// Warnung; Zustand des nichtflchtigen Speichers nicht verndert
+    StorageNotChanged = 0x6200,
+
+    /// Zhler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abhngig)
+    CounterReached = 0x63C0,
+
+    /// Warnung; Zustand des nichtflchtigen Speichers verndert
+    StorageChanged = 0x6300,
+
+    /// Ausfhrungsfehler; Zustand des nichtflchtigen Speichers nicht verndert
+    ExecutionErrorWithoutChange = 0x6400,
+
+    /// Speicherfehler
+    MemoryError = 0x6581,
+
+    /// Ausfhrungsfehler; Zustand des nichtflchtigen Speichers verndert
+    ExecutionErrorWithChange = 0x6500,
+
+    /// Befehlslnge (Lc) oder erwartete Antwortlnge (Le) falsch
+    InvalidLcLe = 0x6700,
+
+    /// Funktionen im Class-Byte werden nicht untersttzt
+    ClassFeatureNotSupported = 0x6800,
+
+    /// Logische Kanle werden nicht untersttzt
+    LogicChannelNotSupported = 0x6881,
+
+    /// Secure Messaging wird nicht untersttzt
+    SecureMessagingNotSupported = 0x6882,
+
+    /// Kommando nicht erlaubt
+    CommandNotAllowed = 0x6900,
+
+    /// Kommando inkompatibel zur Dateistruktur
+    CommandIncompatible = 0x6981,
+
+    /// Sicherheitszustand nicht erfllt
+    SafetyStatusNotFulfilled = 0x6982,
+
+    /// Authentisierungsmethode ist gesperrt
+    AuthenticationMethodLocked = 0x6983,
+
+    /// Referenzierte Daten sind gesperrt
+    ReferencedFileLocked = 0x6984,
+
+    /// Nutzungsbedingungen sind nicht erfllt
+    TermsOfServiceNotFulfilled = 0x6985,
+
+    /// Kommando nicht erlaubt (kein EF selektiert)
+    CommandNotAllowedNoEfSelected = 0x6986,
+
+    /// Erwartete Secure-Messaging-Objekte nicht gefunden
+    ExpectedSecureMessagingObjectsNotFound = 0x6987,
+
+    /// Secure-Messaging-Datenobjekte sind inkorrekt
+    InvalidSecureMessagingObjects = 0x6988,
+
+    /// Falsche Parameter P1/P2
+    WrongParameters = 0x6A00,
+
+    /// Falsche Daten
+    WrongData = 0x6A80,
+
+    /// Funktion wird nicht untersttzt
+    FeatureNotSupported = 0x6A81,
+
+    /// Datei wurde nicht gefunden
+    FileNotFound = 0x6A82,
+
+    /// Datensatz (engl. record) der Datei nicht gefunden
+    RecordNotFound = 0x6A83,
+
+    /// Nicht gengend Speicherplatz in der Datei
+    InsufficientSpace = 0x6A84,
+
+    /// Lc nicht konsistent mit der TLV-Struktur
+    LcTlvInconsistent = 0x6A85,
+
+    /// Inkorrekte Parameter P1/P2
+    IncorrectParameters = 0x6A86,
+
+    /// Lc inkonsistent mit P1/P2
+    LcParametersInconsistent = 0x6A87,
+
+    /// Referenzierte Daten nicht gefunden
+    ReferencedFileNotFound = 0x6A88,
+
+    /// Parameter P1/P2 falsch
+    WrongParameters2 = 0x6B00,
+
+
+    /// Falsche Lnge Le; xx gibt die korrekte Lnge an	Statuswort zur Steuerung des T=0-Protokolls
+    InvalidLe = 0x6C00,
+
+
+    /// Das Kommando (INS) wird nicht untersttzt
+    InstructionNotSupported = 0x6D00,
+
+
+    /// Die Kommandoklasse (CLA) wird nicht untersttzt
+    ClassNotSupported = 0x6E00,
+
+
+    /// Kommando wurde mit unbekanntem Fehler abgebrochen
+    UnknownError = 0x6F00,
+
+    /// Kommando erfolgreich ausgefhrt
+    SUCCESS = 0x9000,
+
+    /// OK
+    OK = 0x9100,
+
+}
+
+#[derive(FromPrimitive)]
+#[repr(u8)]
+pub enum APDUStatusWord2 {
+    OperationOk = 0x00,
+    NoChanges = 0x0C,
+    IllegalCommandCode = 0x1C,
+    IntegrityError = 0x1E,
+    NoSuchKey = 0x40,
+    LengthError = 0x7E,
+    PermissionDenied = 0x9D,
+    ParameterError = 0x9E,
+    AuthenticationDelay = 0xAD,
+    AuthenticationError = 0xAE,
+    AdditionalFrame = 0xAF,
+    BoundaryError = 0xBE,
+    CommandAborted = 0xCA,
+    DuplicateError = 0xDE,
+    FileNotFound = 0xF0,
+}
\ No newline at end of file
diff --git a/src/iso7816_4/mod.rs b/src/iso7816_4/mod.rs
index e69de29..371ce5c 100644
--- a/src/iso7816_4/mod.rs
+++ b/src/iso7816_4/mod.rs
@@ -0,0 +1,3 @@
+pub mod apducommand;
+pub mod apduresponse;
+pub mod apdustatuswords;
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 3d32c68..d5daeb3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,27 @@
+use crate::iso7816_4::apduresponse::APDUResponse;
+use crate::iso7816_4::apducommand::APDUCommand;
+use error::Result;
+
 pub mod crypto;
 pub mod iso7816_4;
 pub mod desfire;
-pub mod error;
\ No newline at end of file
+pub mod error;
+
+pub trait  Card {
+/// <summary>
+/// Connect to Smartcard
+/// </summary>
+fn connect(&self);
+
+/// <summary>
+/// Disconnect from Smartcard
+/// </summary>
+fn disconnect(&self);
+
+/// <summary>
+/// Transmit APDU Command to Smartcard
+/// </summary>
+/// <param name="apdu_cmd">Application Protocol Data Unit Command - ISO 7816</param>
+/// <returns>Application Protocol Data Unit Response - ISO 7816</returns>
+fn transmit(&self, apdu_cmd: APDUCommand) -> Result<APDUResponse>;
+}