⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pscrcb.c

📁 pcmcia智能卡的驱动程序例程
💻 C
📖 第 1 页 / 共 2 页
字号:
			}
		}
	}
	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
		);
	return ( NTStatus );
}

NTSTATUS
CBT1Transmit(
	PSMARTCARD_EXTENSION SmartcardExtension 
	)
/*++

CBT1Transmit:
	finishes the callback RDF_TRANSMIT for the T1 protocol

Arguments:
	SmartcardExtension	context of call

Return Value:
	STATUS_SUCCESS
	STATUS_NO_MEDIA
	STATUS_TIMEOUT
	STATUS_INVALID_DEVICE_REQUEST

--*/
{
    NTSTATUS	NTStatus = STATUS_SUCCESS;
	ULONG		IOBytes;

	SmartcardDebug( 
		DEBUG_TRACE,
		( "PSCR!CBT1Transmit: Enter\n" )
		);
	//
	//	use the lib support to construct the T=1 packets
	//
	do {
		//
		//	no header for the T=1 protocol
		//
		SmartcardExtension->SmartcardRequest.BufferLength = 0;
		//
		//	SCM-TM: Siemens 4440 accepts only NAD=0!!!
		//
		SmartcardExtension->T1.NAD = 0;
		//
		//	let the lib setup the T=1 APDU & check for errors
		//
		NTStatus = SmartcardT1Request( SmartcardExtension );
		if( NT_SUCCESS( NTStatus ))
		{

			//	send command (don't calculate LRC because CRC may be used!)
			IOBytes = 0;
			NTStatus = PscrWriteDirect(
				SmartcardExtension->ReaderExtension,
				SmartcardExtension->SmartcardRequest.Buffer,
				SmartcardExtension->SmartcardRequest.BufferLength,
				&IOBytes
				);
			//
			//	extend the timeout if a Wtx request was sent by the card. if the 
			//	card responds before the waiting time extension expires, the data are
			//	buffered in the reader. A delay without polling the reader status
			//	slows down the performance of the driver, but wtx is an exeption,
			//	not the rule.
			//
			if (SmartcardExtension->T1.Wtx)
			{
					SysDelay(
					(( SmartcardExtension->T1.Wtx * 
					SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
					1000L) 
					);

			}

			//	get response
			SmartcardExtension->SmartcardReply.BufferLength = 0;
			NTStatus = PscrRead(
				SmartcardExtension->ReaderExtension,
				SmartcardExtension->SmartcardReply.Buffer,
				MAX_T1_BLOCK_SIZE,
				&SmartcardExtension->SmartcardReply.BufferLength
				);

			//	if PscrRead detects an LRC error, ignore it (maybe CRC used)
			if( NTStatus == STATUS_CRC_ERROR )
			{
				NTStatus = STATUS_SUCCESS;
			}

            //
            // We even continue if the prev. read failed.
            // We let the smart card library continue, because it might
            // send a resynch. request in case of a timeout
            //
			NTStatus = SmartcardT1Reply( SmartcardExtension );
		}

	//	continue if the lib wants to send the next packet
	} while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );

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

	return ( NTStatus );
}

NTSTATUS
CBT0Transmit( 
	PSMARTCARD_EXTENSION SmartcardExtension 
	)
/*++

CBT0Transmit:
	finishes the callback RDF_TRANSMIT for the T0 protocol

Arguments:
	SmartcardExtension	context of call

Return Value:
	STATUS_SUCCESS
	STATUS_NO_MEDIA
	STATUS_TIMEOUT
	STATUS_INVALID_DEVICE_REQUEST

--*/
{
    NTSTATUS NTStatus = STATUS_SUCCESS;
	PUCHAR pRequest,pReply;
	ULONG IOBytes, APDULength, RequestLength;
	UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
    UCHAR WtxReply[16];

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!CBT0Transmit: Enter\n" )
		);

	pRequest	= SmartcardExtension->SmartcardRequest.Buffer;
	pReply		= SmartcardExtension->SmartcardReply.Buffer;

	//	setup the command header
	pRequest[ PSCR_NAD ] = 
		( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ? 
		NAD_TO_ICC1 : NAD_TO_ICC1;

	pRequest[ PSCR_PCB ] = PCB_DEFAULT;
	//
	//	get the length of the user data packet & set the appropriate LEN
	//	information the complete user packet consists of a SCARD_IO_REQUEST
	//	structure followed by the APDU. the length of SCARD_IO_REQUEST is
	//	transferred in the member cbPciLength of the structure
	//
	APDULength = SmartcardExtension->IoRequest.RequestBufferLength;
	APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension->
		IoRequest.RequestBuffer)->cbPciLength;
	//
	//	a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see
	//	annex of the ISO
	//
	if( APDULength == 4 ) APDULength++;
	//
	//	if the total length of the T1 (reader) packet is larger than 0xFF
	//	the extended length notation will be used
	//
	if( APDULength >= 0xFF )
	{
		pRequest[ PSCR_LEN ]	= 0xFF;
		pRequest[ PSCR_LEN+1 ]	= HIBYTE( APDULength );
		pRequest[ PSCR_LEN+2 ]	= LOBYTE( APDULength );
		SmartcardExtension->SmartcardRequest.BufferLength =
			PSCR_EXT_PROLOGUE_LENGTH;
	}
	else
	{
		pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength;
		SmartcardExtension->SmartcardRequest.BufferLength = 
			PSCR_PROLOGUE_LENGTH;
	}

	//	let the lib setup the T=1 APDU & check for errors
	NTStatus = SmartcardT0Request( SmartcardExtension );
    RequestLength = SmartcardExtension->SmartcardRequest.BufferLength;

	while( NT_SUCCESS( NTStatus ))
	{
		//	send command
		IOBytes = 0;
		NTStatus = PscrWrite(
			SmartcardExtension->ReaderExtension,
			pRequest,
			RequestLength,
			&IOBytes
			);

		//	get response
		if( NT_SUCCESS( NTStatus ))
		{
			IOBytes = 0;
			NTStatus = PscrRead(
				SmartcardExtension->ReaderExtension,
				IOData,
				MAX_T1_BLOCK_SIZE,
				&IOBytes
				);

			//	extract APDU from T=1 transport packet
			if( NT_SUCCESS( NTStatus ))
			{
                if (IOData[ PSCR_PCB ] == WTX_REQUEST) {

                    WtxReply[PSCR_NAD] = NAD_TO_PSCR;
                    WtxReply[PSCR_PCB] = WTX_REPLY;
                    WtxReply[PSCR_LEN] = 1;
                    WtxReply[PSCR_INF] = IOData[PSCR_INF];

                    RequestLength = 4;
                    pRequest = WtxReply;
                    continue;
                }

				if( IOData[ PSCR_LEN ] == 0xFF )
				{
					//
					//	extended length byte used
					//
					APDULength  = IOData[ PSCR_LEN + 1 ] << 8;
					APDULength += IOData[ PSCR_LEN + 2 ];

					SmartcardExtension->SmartcardReply.BufferLength = APDULength ;
					SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength );
				}
				else
				{
					SmartcardExtension->SmartcardReply.BufferLength = 
						IOData[ PSCR_LEN ];

					SysCopyMemory( 
						pReply, 
						&IOData[ PSCR_APDU ], 
						IOData[ PSCR_LEN ] 
						);
				}

				// let the lib evaluate the result & tansfer the data
				NTStatus = SmartcardT0Reply( SmartcardExtension );
                break;
			}
		}
	}

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

    return( NTStatus );
}

NTSTATUS
CBCardTracking( 
	PSMARTCARD_EXTENSION SmartcardExtension 
	)
/*++

CBCardTracking:
	callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was 
	validated by the smclib (i.e. a card removal request will only be passed 
	if a card is present).
	for a win95 build STATUS_PENDING will be returned without any other action. 
	for NT the cancel routine for the irp will be set to the drivers cancel
	routine.

Arguments:
	SmartcardExtension	context of call

Return Value:
	STATUS_PENDING

--*/
{
	KIRQL CancelIrql;

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!CBCardTracking: Enter\n" )
		);

	//	set cancel routine
	IoAcquireCancelSpinLock( &CancelIrql );

	IoSetCancelRoutine(
		SmartcardExtension->OsData->NotificationIrp, 
		PscrCancel
		);

	IoReleaseCancelSpinLock( CancelIrql );

	SmartcardDebug( 
		DEBUG_TRACE,
		( "PSCR!CBCardTracking: Exit \n" )
		);

	return( STATUS_PENDING );
}

VOID
CBUpdateCardState(
	PSMARTCARD_EXTENSION SmartcardExtension,
    UCHAR IccState,
    BOOLEAN SystemWakeUp
	)
{
    ULONG oldState;
    KIRQL currentIrql, irql;

    KeAcquireSpinLock(
        &SmartcardExtension->OsData->SpinLock,
        &irql
        );

	SmartcardDebug( 
		DEBUG_TRACE,
		( "PSCR!CBUpdateCardState: Enter \n" )
		);

    oldState = 
        (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ?
        SCARD_PRESENT : SCARD_ABSENT);

	SmartcardExtension->ReaderCapabilities.CurrentState = 
        (IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT);

	SmartcardDebug( 
		DEBUG_DRIVER, 
		( "PSCR!CBUpdateCardState: Smart card %s\n",
        IccState == PSCR_ICC_PRESENT ? "inserted" : "removed")
		);

    IoAcquireCancelSpinLock( &currentIrql );

	if( SmartcardExtension->OsData->NotificationIrp != NULL && (
            SystemWakeUp && (
                oldState == SCARD_PRESENT || 
                SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) || 
            SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) {

        PIRP notificationIrp = InterlockedExchangePointer(
            &(SmartcardExtension->OsData->NotificationIrp),
            NULL
            );

		IoSetCancelRoutine( 
            notificationIrp, 
            NULL 
            );

		IoReleaseCancelSpinLock( currentIrql );

        if (notificationIrp->Cancel == FALSE) {
         	
		    //	finish the request
		    notificationIrp->IoStatus.Status	= STATUS_SUCCESS;
		    notificationIrp->IoStatus.Information = 0;

	        SmartcardDebug( 
		        DEBUG_DRIVER, 
		        ( "PSCR!CBUpdateCardState: Completing Irp %lx\n",
                notificationIrp)
		        );

		    IoCompleteRequest(notificationIrp, IO_NO_INCREMENT );
        }

    } else {
     	
		IoReleaseCancelSpinLock( currentIrql );
    }

	SmartcardDebug( 
		DEBUG_TRACE,
		( "PSCR!CBUpdateCardState: Exit \n" )
		);

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

UCHAR 
CBGetCardState(
	PSMARTCARD_EXTENSION SmartcardExtension 
	)
/*++

CBUpdateCardState:
	updates the variable CurrentState in SmartcardExtension

Arguments:
	SmartcardExtension	context of call

Return Value:
	STATUS_SUCCESS

--*/
{
	NTSTATUS NTStatus = STATUS_SUCCESS;
	UCHAR TLVList[ TLV_BUFFER_SIZE ],	Val, Len;
	ULONG TLVListLen;
	PREADER_EXTENSION	ReaderExtension = SmartcardExtension->ReaderExtension;

	//	read the status file of ICC1 from the reader
	TLVListLen = TLV_BUFFER_SIZE;

	if( NT_SUCCESS( CmdReadStatusFile(
		ReaderExtension,
		ReaderExtension->Device,
		TLVList,
		&TLVListLen
		)))	{

		//	get reader status value
		CmdGetTagValue(
			TAG_READER_STATUS,
			TLVList,
			TLVListLen,
			&Len,
			( PVOID ) &Val
			);
	}
	else
	{
		//	IO-error is interpreted as card absent
        ASSERT(FALSE);
		Val = PSCR_ICC_ABSENT;
	}

    return Val;
}

//	-------------------------------- END OF FILE ------------------------------



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -