Beispiel #1
0
NTSTATUS
CBCardPower(
           PSMARTCARD_EXTENSION SmartcardExtension
           )
/*++

CBCardPower:
        callback handler for SMCLIB RDF_CARD_POWER

Arguments:
        SmartcardExtension      context of call

Return Value:
        STATUS_SUCCESS
        STATUS_NO_MEDIA
        STATUS_TIMEOUT
        STATUS_BUFFER_TOO_SMALL

--*/
{
    NTSTATUS                        NTStatus = STATUS_SUCCESS;
    UCHAR                           ATRBuffer[ ATR_SIZE ], TLVList[16];
    ULONG                           Command,
    ATRLength = 0;
    PREADER_EXTENSION       ReaderExtension;
    BYTE                CardState;
    KIRQL               irql;
#if DBG || DEBUG
    static PCHAR request[] = { "PowerDown",  "ColdReset", "WarmReset"};
#endif

    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBCardPower: Enter, Request = %s\n",
                    request[SmartcardExtension->MinorIoControlCode])
                  );

    ReaderExtension = SmartcardExtension->ReaderExtension;

        //
        //      update actual power state
        //
    Command = SmartcardExtension->MinorIoControlCode;

    switch ( Command ) {
    case SCARD_WARM_RESET:

        //      if the card was not powerd, fall thru to cold reset
        KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
                          &irql);

        if ( SmartcardExtension->ReaderCapabilities.CurrentState >
             SCARD_SWALLOWED ) {
            KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
                              irql);

                                //      reset the card
            ATRLength = ATR_SIZE;
            NTStatus = CmdReset(
                               ReaderExtension,
                               ReaderExtension->Device,
                               TRUE,                           // warm reset
                               ATRBuffer,
                               &ATRLength
                               );

            break;
        } else {
            KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
                              irql);

        }

                        //      warm reset not possible because card was not powerd
    case SCARD_COLD_RESET:

                        //      reset the card
        ATRLength = ATR_SIZE;
        NTStatus = CmdReset(
                           ReaderExtension,
                           ReaderExtension->Device,
                           FALSE,                          // cold reset
                           ATRBuffer,
                           &ATRLength
                           );
        break;

    case SCARD_POWER_DOWN:
        ATRLength = 0;
        NTStatus = CmdDeactivate(
                                ReaderExtension,
                                ReaderExtension->Device
                                );

                        //      discard old card status
        CardState = CBGetCardState(SmartcardExtension);
        CBUpdateCardState(SmartcardExtension, CardState, FALSE);
        break;
    }

    if (NT_SUCCESS(NTStatus)) {

        //
        // Set the 'restart of work waiting time' counter for T=0
        // This will send a WTX request for n NULL bytes received
        //
        TLVList[0] = TAG_SET_NULL_BYTES;
        TLVList[1] = 1;
        TLVList[2] = 0x05;

        NTStatus = CmdSetInterfaceParameter(
                                           ReaderExtension,
                                           DEVICE_READER,
                                           TLVList,
                                           3
                                           );
    }

    // Removing this assert as this causes unnecessary confusion.  The driver
    // passes ifdtest even with an error here.
    // NT_ASSERT(NT_SUCCESS(NTStatus));

        //      finish the request
    if ( NT_SUCCESS( NTStatus )) {
                //      update all neccessary data if an ATR was received
        if ( ATRLength > 2 ) {
                        //
                        //      the lib expects only the ATR, so we skip the
                        //      900x from the reader
                        //
            ATRLength -= 2;

                        //      copy ATR to user buffer buffer
            if ( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength ) {
                SysCopyMemory(
                             SmartcardExtension->IoRequest.ReplyBuffer,
                             ATRBuffer,
                             ATRLength
                             );
                *SmartcardExtension->IoRequest.Information = ATRLength;
            }

                        //      copy ATR to card capability buffer
            if ( ATRLength <= MAXIMUM_ATR_LENGTH ) {
                SysCopyMemory(
                             SmartcardExtension->CardCapabilities.ATR.Buffer,
                             ATRBuffer,
                             ATRLength
                             );

                SmartcardExtension->CardCapabilities.ATR.Length =
                ( UCHAR )ATRLength;

                                //      let the lib update the card capabilities
                NTStatus = SmartcardUpdateCardCapabilities(
                                                          SmartcardExtension
                                                          );
            } else {
                NTStatus = STATUS_BUFFER_TOO_SMALL;
            }
        }
    }

    if ( !NT_SUCCESS( NTStatus )) {
        switch ( NTStatus ) {
        case STATUS_NO_MEDIA:
        case STATUS_BUFFER_TOO_SMALL:
            break;

        case STATUS_TIMEOUT:
            NTStatus = STATUS_IO_TIMEOUT;
            break;

        default:
            NTStatus = STATUS_UNRECOGNIZED_MEDIA;
            break;
        }
        if( NTStatus != STATUS_SUCCESS )
        {

            // notify resman if card was removed
            CBUpdateCardState(
                SmartcardExtension,
                CBGetCardState( SmartcardExtension ),
                FALSE
                );

            // resman requires status ok to translate ntstatus to scard... error.
            if( SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT )
            {
                SmartcardUpdateCardCapabilities( SmartcardExtension );
                NTStatus = STATUS_SUCCESS;
            }
        }
    }

    // start freeze routine, if an interrupt was sent, but no freeze data was read
    if( SmartcardExtension->ReaderExtension->RequestInterrupt )
        PscrFreeze( SmartcardExtension );

    // Clearing the buffers
    RtlZeroMemory (ATRBuffer, ATR_SIZE);
    RtlZeroMemory (TLVList, 16);

    SmartcardDebug(
                  DEBUG_TRACE,
                  ( "PSCR!CBCardPower: Exit (%lx)\n", NTStatus )
                  );

    return( NTStatus );
}
Beispiel #2
0
/*!
 * \brief Function resets a smart card and return ATR.<br>
 * <br>
 * \param [in] pSmartcardExtension A pointer to the smart card extension,
		SMARTCARD_EXTENSION, of the device.
 *
 * \retval STATUS_SUCCESS the routine successfully end.
 * \retval STATUS_IO_TIMEOUT The request timed out.
 * \retval STATUS_BUFFER_TOO_SMALL Expected ATR Length is too small.
 * \retval STATUS_NO_MEDIA Other errors during initalization(No smart card is
	inserted in the reader).
 */
static NTSTATUS resetCard(PSMARTCARD_EXTENSION pSmartcardExtension)
{
	dbg_log("resetCard start");
	NTSTATUS status = STATUS_SUCCESS;

	if (pSmartcardExtension->IoRequest.ReplyBufferLength < JCOP_PROXY_MAX_ATR_SIZE) {
		dbg_log(
		    "STATUS_BUFFER_TOO_SMALL - pSmartcardExtension->IoRequest.ReplyBufferLength: %d",
		    pSmartcardExtension->IoRequest.ReplyBufferLength
		);
		return STATUS_BUFFER_TOO_SMALL;
	}

	PREADER_EXTENSION pReaderExtension = pSmartcardExtension->ReaderExtension;

	// send "Wait for card" message.
	unsigned char mty = 0x00;	// MTY 0x00(Wait for card)
	unsigned char nad = 0x21;	// NAD
	char pSnd[4];	// PY0 payload (interpretation depends on message type)
	RtlZeroMemory(pSnd, 4);

	unsigned short atrLen;
	char atr[JCOP_PROXY_MAX_ATR_SIZE];

	long msec = 1000;	// wait for 1sec.
	LARGE_INTEGER dueTime;
	dueTime.QuadPart = -10000 * msec;

	status = sendMessage(
	             pReaderExtension,
	             mty,
	             nad,
	             pSnd,
	             4,
	             atr,
	             (unsigned short)pSmartcardExtension->IoRequest.ReplyBufferLength,
	             &atrLen,
	             &dueTime
	         );
	if (status != STATUS_SUCCESS) {
		dbg_log("sendResetMessage failed! - status: 0x%08X", status);
		switch (status) {
			case STATUS_IO_TIMEOUT :
				return STATUS_IO_TIMEOUT;
			case STATUS_BUFFER_TOO_SMALL :
				return STATUS_BUFFER_TOO_SMALL;
			default :
				return STATUS_NO_MEDIA;
		}
	}

	// On output, the structure pointed to by SmartcardExtension should
	// have the following values:
	//
	//  - IoRequest.ReplyBuffer
	// 		Receives the ATR that is returned by the smart card. In addition,
	// 		you must transfer the ATR to SmartcardExtension->CardCapabilities.ATR.Buffer
	// 		so that the library can parse the ATR.
	//  - IoRequest.Information
	// 		Receives the length of the ATR.
	//  - CardCapabilities.ATR.Length
	// 		Contains the length of the ATR.
	//
	// http://msdn2.microsoft.com/en-us/library/ms801315.aspx
	RtlCopyMemory(pSmartcardExtension->IoRequest.ReplyBuffer, atr, atrLen);
	*pSmartcardExtension->IoRequest.Information = atrLen;

	// set state the reader connected, but the card has been reset.
	pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;

	// The SmartcardUpdateCardCapabilities routine translates an answer-to-reset (ATR)
	// string into the SCARD_CARD_CAPABILITIES structure that the driver can use.
	// http://msdn2.microsoft.com/en-us/library/ms801323.aspx
	RtlCopyMemory(pSmartcardExtension->CardCapabilities.ATR.Buffer, atr, atrLen);
	pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)atrLen;
	status = SmartcardUpdateCardCapabilities(pSmartcardExtension);
	if (status != STATUS_SUCCESS) {
		dbg_log("SmartcardUpdateCardCapabilities failed! - status: 0x%08X", status);
		return status;
	}

	//pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
	//pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;

	dbg_log("resetCard end - status: 0x%08X", status);
	return status;
}