/// <summary>
        /// Wraps the PCSC function
        /// LONG SCardTransmit(
        ///		SCARDHANDLE hCard,
        ///		LPCSCARD_I0_REQUEST pioSendPci,
        ///		LPCBYTE pbSendBuffer,
        ///		DWORD cbSendLength,
        ///		LPSCARD_IO_REQUEST pioRecvPci,
        ///		LPBYTE pbRecvBuffer,
        ///		LPDWORD pcbRecvLength
        ///	);
        /// </summary>
        /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
        /// <returns>An APDUResponse object with the response from the card</returns>
        public override APDUResponse Transmit(APDUCommand ApduCmd)
        {
            // Must verify that it works with all type of cards
            uint outputLength = (ApduCmd.Le == 0)
                ? APDUResponse.MAX_LENGHT
                :(ApduCmd.Le + APDUResponse.SW_LENGTH);

            byte[] ApduBuffer   = null;
            byte[] ApduResponse = new byte[outputLength];

            PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request();
            ioRequest.Protocol  = protocol;
            ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest);

            // Build the command APDU
            if (ApduCmd.Data == null)
            {
                ApduBuffer    = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well
                ApduBuffer[4] = (byte)ApduCmd.Le;
            }
            else
            {
                int apduBufferLengh = (ApduCmd.Class == 0x90)
                    ? APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length + 1
                    : APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length;

                ApduBuffer = new byte[apduBufferLengh];
                Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length);
                ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
                if (ApduCmd.Class == 0x90)
                {
                    ApduBuffer[apduBufferLengh - 1] = 0;
                }
            }

            ApduBuffer[0] = ApduCmd.Class;
            ApduBuffer[1] = ApduCmd.Ins;
            ApduBuffer[2] = ApduCmd.P1;
            ApduBuffer[3] = ApduCmd.P2;

            lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength);
            ThrowSmartcardException("SCardTransmit", lastError);

            byte[] responseData = new byte[outputLength];
            Buffer.BlockCopy(ApduResponse, 0, responseData, 0, (int)outputLength);
            string apduString = string.Format("APDU Buffer[{0}] => Response[{1}]", ByteArray.ToString(ApduBuffer), ByteArray.ToString(responseData));

            apduTrace.Add(apduString);
            Trace.WriteLine(apduString);

            return(new APDUResponse(responseData));
        }
        /// <summary>
        /// Wraps the PCSC function
        /// LONG SCardTransmit(
        ///		SCARDHANDLE hCard,
        ///		LPCSCARD_I0_REQUEST pioSendPci,
        ///		LPCBYTE pbSendBuffer,
        ///		DWORD cbSendLength,
        ///		LPSCARD_IO_REQUEST pioRecvPci,
        ///		LPBYTE pbRecvBuffer,
        ///		LPDWORD pcbRecvLength
        ///	);
        /// </summary>
        /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param>
        /// <returns>An APDUResponse object with the response from the card</returns>
        public override APDUResponse Transmit(APDUCommand ApduCmd)
        {
            // Must verify that it works with all type of cards
            uint outputLength = (ApduCmd.Le == 0)
                ? APDUResponse.MAX_LENGHT
                : (ApduCmd.Le + APDUResponse.SW_LENGTH);

            byte[] ApduBuffer   = null;
            byte[] ApduResponse = new byte[outputLength];

            PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request();
            ioRequest.Protocol  = protocol;
            ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest);

            // Build the command APDU
            if (ApduCmd.Data == null)
            {
                ApduBuffer    = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well
                ApduBuffer[4] = (byte)ApduCmd.Le;
            }
            else
            {
                ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
                Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length);
                ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
            }

            ApduBuffer[0] = ApduCmd.Class;
            ApduBuffer[1] = ApduCmd.Ins;
            ApduBuffer[2] = ApduCmd.P1;
            ApduBuffer[3] = ApduCmd.P2;

            lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength);
            ThrowSmartcardException("SCardTransmit", lastError);

            byte[] ApduData = new byte[outputLength];
            Buffer.BlockCopy(ApduResponse, 0, ApduData, 0, (int)outputLength);

            return(new APDUResponse(ApduData));
        }