/// <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); }
/// <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); }