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