/// <summary>
        /// Sends an APDU to the device connected to the underlying driver.
        /// </summary>
        /// <param name="apdu">APDU to send to the device</param>
        /// <returns>Returns an <see cref="APDUResponse"/> containing response status code and any data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="apdu"/> is null.</exception>
        /// <exception cref="UnexpectedResponseException">Thrown on a non-success status code.</exception>
        public APDUResponse SendAPDU(APDU apdu)
        {
            // Send APDU and parse response
            APDUResponse res = Driver.SendAPDU(apdu, null);

            // Read remaining data
            while (res.SW1 == (byte)APDUResponse.StatusWord.MORE_DATA_AVAILABLE)
            {
                APDUResponse _res = Driver.SendAPDU(new APDU
                {
                    CLA = 0x00,
                    INS = (APDU.Instruction)Instruction.SEND_REMAINING,
                    P1  = 0x00,
                    P2  = 0x00
                }, null);

                // Extend res.Data with remaining data
                int offset = res.Data.Length;
                Array.Resize(ref res.Data, offset + _res.Data.Length);
                Buffer.BlockCopy(_res.Data, 0, res.Data, offset, _res.Data.Length);

                // Overwrite status words
                res.SW = _res.SW;
            }

            // Validate final status
            if (res.SW != APDUResponse.StatusWord.SUCCESS)
            {
                throw new UnexpectedResponseException("Unexpected response from device.", res.SW);
            }

            // Return full response
            return(res);
        }
Пример #2
0
        /// <summary>
        /// Transmits an <see cref="APDU"/> to the device and receives an <see cref="APDUResponse"/> back from it.
        /// </summary>
        /// <param name="apdu">APDU to send to the device</param>
        /// <param name="check">Status code to check for</param>
        /// <returns>Returns the parsed <see cref="APDUResponse"/> from the device response.</returns>
        /// <exception cref="UnexpectedResponseException">Thrown if write is unsuccessful or device returns a status code not matching <paramref name="check"/>.</exception>
        public APDUResponse SendAPDU(APDU apdu, APDUResponse.StatusWord?check = APDUResponse.StatusWord.SUCCESS)
        {
            if (apdu == null)
            {
                throw new ArgumentNullException();
            }

            byte[]     buffer   = new byte[256];
            SCardError writeres = Reader.Transmit(apdu.ToBytes(), ref buffer);

            if (writeres != SCardError.Success)
            {
                throw new UnexpectedResponseException("Device returned a non-success status code.");
            }

            APDUResponse res = new APDUResponse(buffer);

            if (check != null && check != res.SW)
            {
                throw new UnexpectedResponseException("Unexpected response from device.");
            }

            return(res);
        }