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

📄 pscrcmd.c

📁 pcmcia智能卡的驱动程序例程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1997 - 1999 SCM Microsystems, Inc.

Module Name:

    PscrCmd.c

Abstract:

	Basic command functions for SCM PSCR smartcard reader

Author:

	Andreas Straub

Environment:


	Win 95		Sys... calls are resolved by Pscr95Wrap.asm functions and
				Pscr95Wrap.h macros, resp.

	NT	4.0		Sys... functions resolved by PscrNTWrap.c functions and
				PscrNTWrap.h macros, resp.

Revision History:

	Andreas Straub			8/18/1997	1.00	Initial Version
	Andreas Straub			9/24/1997	1.02	delay for read/write removed

--*/

#if defined( SMCLIB_VXD )

#include <Pscr95.h>

#else	//	SMCLIB_VXD

#include <PscrNT.h>

#endif	//	SMCLIB_VXD

#include <PscrRdWr.h>
#include <PscrCmd.h>

NTSTATUS
CmdResetInterface(	
	PREADER_EXTENSION ReaderExtension 
	)
/*++
CmdResetInterface:

	Performs a reset of the reader interface (NOT of the PCMCIA controller)
	- flush available data
	- set RESET bit
	- perform a buffer size exchange between reader & host
	- enables interrupts for freeze events
	- disables default PTS

Arguments:
	ReaderExtension	context of call

Return Value:
	STATUS_SUCCESS
	STATUS_IO_DEVICE_ERROR

--*/
{

	NTSTATUS		NTStatus = STATUS_SUCCESS;
	ULONG			IOBytes;
	UCHAR			Len,
					Tag,
					Cnt,
					InData[ TLV_BUFFER_SIZE ];
	PPSCR_REGISTERS	IOBase;
	UCHAR			EnableInterrupts[]	= { 0x28, 0x01, 0x01 };


	IOBase = ReaderExtension->IOBase;

	//	discard any data
	PscrFlushInterface( ReaderExtension );

	//	reset reader
	WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_RESET_BIT );
	SysDelay( DELAY_WRITE_PSCR_REG );
	WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );

	NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );

	//	read & check vendor string
	if( NT_SUCCESS( NTStatus ))
	{

		WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
		SysDelay( DELAY_WRITE_PSCR_REG );
		//
		//	get actual len from TLV list
		//
		READ_PORT_UCHAR( &IOBase->SizeMSReg );
		READ_PORT_UCHAR( &IOBase->SizeLSReg );

		Tag = READ_PORT_UCHAR( &IOBase->DataReg );
		Len = READ_PORT_UCHAR( &IOBase->DataReg );
		//
		//	avoid overwrite of buffer
		//
		if( Len > TLV_BUFFER_SIZE )
		{
			Len = TLV_BUFFER_SIZE;
		}
		for ( Cnt = 0; Cnt < Len; Cnt++ )
		{
			InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
		}
		WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
		//
		//	check vendor string
		//
		if( SysCompareMemory(
						InData,
						PSCR_ID_STRING,
						sizeof( PSCR_ID_STRING )
						))
		{
			NTStatus = STATUS_IO_DEVICE_ERROR;
		}
		else
		{
			//
			//	vendor string was correct, check buffer size
			//
			WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_READ_BIT );
			NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );
			//
			//	reader ready to transfer interface buffer size
			//
			if( NT_SUCCESS( NTStatus ))
			{
				//
				//	set size read & host control
				//
				WRITE_PORT_UCHAR(
					&IOBase->CmdStatusReg,
					PSCR_SIZE_READ_BIT | PSCR_HOST_CONTROL_BIT
					);

				SysDelay( DELAY_WRITE_PSCR_REG );
				//
				//	read buffer length
				//
				Len = READ_PORT_UCHAR( &IOBase->SizeMSReg );
				Len = READ_PORT_UCHAR( &IOBase->SizeLSReg );
				for ( Cnt = 0; Cnt < Len; Cnt++ )
				{
					InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
				}
				//
				//	transfer of interface buffer size okay
				//
				WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
				SysDelay( DELAY_WRITE_PSCR_REG );
				//
				//	notify the reader about the supported buffer size
				//
				WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
				SysDelay( DELAY_WRITE_PSCR_REG );

				WRITE_PORT_UCHAR( &IOBase->SizeMSReg, 0 );
				WRITE_PORT_UCHAR( &IOBase->SizeLSReg, 2 );
				//
				//	Write the same data buffer size as the one we just got.
				//
				WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 0 ] );
				WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 1 ] );
				//
				//	store the size to report to the lib
				//  The maximum buffer size of the reader is to betrieved with 
                //  ((ULONG)InData[ 1 ] << 8) | InData[ 0 ]
                //
				ReaderExtension->MaxIFSD = 254;
					
				//
				//	let the reader process the size write command
				//
				WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_WRITE_BIT );
				NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
			}
		}
	}
	//
	//	clean up any host control settings
	//
	WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
	//
	//	enable interrupts
	//
	CmdSetInterfaceParameter( 
		ReaderExtension, 
		ReaderExtension->Device,
		EnableInterrupts,
		sizeof( EnableInterrupts )
		);

	return ( NTStatus );
}

NTSTATUS
CmdReset( 
	PREADER_EXTENSION	ReaderExtension,
	UCHAR				Device,
	BOOLEAN				WarmReset,
	PUCHAR				pATR,
	PULONG				pATRLength
	)
/*++
CmdReset:
	performs a reset of the reader / ICC

Arguments:
	ReaderExtension		context of call
	Device				device requested ( ICC_1, ICC_2, PSCR )
	WarmReset			kind of ICC reset
	pATR				ptr to ATR buffer, NULL if no ATR required
	pATRLength			size of ATR buffer / length of ATR

Return Value:
	STATUS_SUCCESS
	STATUS_NO_MEDIA
	STATUS_UNRECOGNIZED_MEDIA
	error values from PscrRead / PscrWrite

--*/
{
	NTSTATUS	NTStatus = STATUS_SUCCESS;
	UCHAR		IOData[ MAX_T1_BLOCK_SIZE ],
				P2;
	USHORT		ICCStatus;
	ULONG		IOBytes;

	//	ATR from the smartcard requestet? P2 = 1
	P2 = 0;
	if(( pATR != NULL ) && ( pATRLength != NULL ))
	{
		if( *pATRLength > 0 )
			P2 = 0x01;
	}

	//	build the RESET command.
	IOData[ PSCR_NAD ] = NAD_TO_PSCR;
	IOData[ PSCR_PCB ] = PCB_DEFAULT;
	IOData[ PSCR_LEN ] = 0x05;

	if( WarmReset == TRUE )
	{
		IOData[ PSCR_INF+0 ] = CLA_WARM_RESET;
		IOData[ PSCR_INF+1 ] = INS_WARM_RESET;
	}
	else
	{
		IOData[ PSCR_INF+0 ] = CLA_RESET;
		IOData[ PSCR_INF+1 ] = INS_RESET;
	}
	IOData[ PSCR_INF+2 ] = Device;
	IOData[ PSCR_INF+3 ] = P2;
	IOData[ PSCR_INF+4 ] = 0x00;

	//	write command
	NTStatus = PscrWrite(
		ReaderExtension,
		IOData,
		8,
		&IOBytes
		);

	if( NT_SUCCESS( NTStatus ))
	{
		//	read data
		IOBytes = 0;
		NTStatus = PscrRead(
			ReaderExtension,
			IOData,
			MAX_T1_BLOCK_SIZE,
			&IOBytes
			);

		//	error detection
		if( NT_SUCCESS( NTStatus ))
		{
			//
			// the location of the error code in the buffer
			// is: ( data ) - STATUS_MSB - STATUS_LSB - EPILOGUE
			//
			ICCStatus = (( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-2 ]) << 8;
			ICCStatus |= ( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-1 ];

			switch( ICCStatus )
			{
				case PSCR_SW_SYNC_ATR_SUCCESS:
				case PSCR_SW_ASYNC_ATR_SUCCESS:
					break;

				case PSCR_SW_NO_ICC:
					NTStatus = STATUS_NO_MEDIA;
					break;

				case PSCR_SW_NO_PROTOCOL:
				case PSCR_SW_NO_ATR:
				case PSCR_SW_NO_ATR_OR_PROTOCOL:
				case PSCR_SW_NO_ATR_OR_PROTOCOL2:
				case PSCR_SW_ICC_NOT_ACTIVE:
				case PSCR_SW_NON_SUPPORTED_PROTOCOL:
				case PSCR_SW_PROTOCOL_ERROR:
				default:
					NTStatus = STATUS_UNRECOGNIZED_MEDIA;
			}
			//
			//	copy ATR if required
			//
			if( NT_SUCCESS( NTStatus ))
			{
				if( P2 == 0x01 )
				{
					IOBytes -= PSCR_PROLOGUE_LENGTH + PSCR_EPILOGUE_LENGTH;
					if( IOBytes > *pATRLength )
					{
						IOBytes = *pATRLength;
					}
					SysCopyMemory(	
						pATR, 
						&IOData[ PSCR_PROLOGUE_LENGTH ], 
						IOBytes 
						);
					*pATRLength = IOBytes;
				}
			}
		}
	}
	return( NTStatus );
}


NTSTATUS
CmdDeactivate( 
	PREADER_EXTENSION	ReaderExtension,
	UCHAR				Device
	)
/*++
CmdDeactivate:
	Deactivates the requested device

Arguments:
	ReaderExtension		context of call
	Device				requested device

Return Value:
	STATUS_SUCCESS
	error values from PscrRead / PscrWrite

--*/
{
	NTSTATUS	NTStatus = STATUS_SUCCESS;
	UCHAR		IOData[  MAX_T1_BLOCK_SIZE ];
	ULONG		IOBytes;

	//
	//	build the DEACTIVATE command.
	//
	IOData[ PSCR_NAD ] = NAD_TO_PSCR;
	IOData[ PSCR_PCB ] = PCB_DEFAULT;
	IOData[ PSCR_LEN ] = 0x05;

	IOData[ PSCR_INF+0 ] = CLA_DEACTIVATE;
	IOData[ PSCR_INF+1 ] = INS_DEACTIVATE;
	IOData[ PSCR_INF+2 ] = Device;
	IOData[ PSCR_INF+3 ] = 0x00;
	IOData[ PSCR_INF+4 ] = 0x00;
	//
	//	write command
	//
	NTStatus = PscrWrite(
		ReaderExtension,
		IOData,
		8,
		&IOBytes
		);

	if( NT_SUCCESS( NTStatus ))
	{
		//
		//	read data to trap communication errors
		//
		IOBytes = 0;
		NTStatus = PscrRead(
			ReaderExtension,
			IOData,
			MAX_T1_BLOCK_SIZE,
			&IOBytes
			);
	}
	return( NTStatus );
}

NTSTATUS
CmdReadBinary(
	PREADER_EXTENSION	ReaderExtension,
	USHORT				Offset,
	PUCHAR				pBuffer,
	PULONG				pBufferLength
	)
/*++
CmdReadBinary:
	read binary data from an PSCR data file

Arguments:
	ReaderExtension		context of call
	Offset				offset in file
	pBuffer				ptr to data buffer
	pBufferLength		length of buffer / number of bytes read

Return Value:

	STATUS_SUCCESS
	STATUS_UNSUCCESSFUL
	error values from PscrRead / PscrWrite

--*/
{
    NTSTATUS	NTStatus = STATUS_SUCCESS;
    UCHAR		IOData[ MAX_T1_BLOCK_SIZE ];
	USHORT		ICCStatus;
	ULONG		IOBytes;
	// 
	//	check parameters
	//
	if(( pBuffer == NULL ) || ( pBufferLength == NULL))
	{
		NTStatus = STATUS_INVALID_PARAMETER;
	}
	else
	{
		//
		//	build the READ BINARY command
		//
		IOData[ PSCR_NAD] = NAD_TO_PSCR;
		IOData[ PSCR_PCB] = PCB_DEFAULT;
		IOData[ PSCR_LEN] = 0x05;

		IOData[ PSCR_INF+0 ] = CLA_READ_BINARY;
		IOData[ PSCR_INF+1 ] = INS_READ_BINARY;
		IOData[ PSCR_INF+2 ] = HIBYTE( Offset );
		IOData[ PSCR_INF+3 ] = LOBYTE( Offset );
		IOData[ PSCR_INF+4 ] = 0x00;
		//
		//	write command
		//
		NTStatus = PscrWrite(
			ReaderExtension,
			IOData,
			8,
			&IOBytes
			);

		if( NT_SUCCESS( NTStatus ))
		{
			//
			//	read data
			//
			IOBytes = 0;
			NTStatus = PscrRead(
				ReaderExtension,
				IOData,
				MAX_T1_BLOCK_SIZE,
				&IOBytes
				);
			
			if( NT_SUCCESS( NTStatus ))
			{
				//
				//	error check
				//
				ICCStatus = 
					((USHORT)IOData[ IOBytes-2-PSCR_EPILOGUE_LENGTH ]) << 8;
				ICCStatus |= 
					(USHORT)IOData[ IOBytes-1-PSCR_EPILOGUE_LENGTH ];

				switch( ICCStatus )
				{
					case PSCR_SW_FILE_NO_ACCEPPTED_AUTH:
					case PSCR_SW_FILE_NO_ACCESS:
					case PSCR_SW_FILE_BAD_OFFSET:
					case PSCR_SW_END_OF_FILE_READ:
						NTStatus = STATUS_UNSUCCESSFUL;
						break;
					default:
						break;
				}
				//
				//	copy data
				//
				if( NT_SUCCESS( NTStatus ))
				{
					if( *pBufferLength < 
						IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH )
					{
						NTStatus = STATUS_BUFFER_TOO_SMALL;
					}
					else
					{
						( *pBufferLength ) = 
							IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH;
						SysCopyMemory( 
							pBuffer, 
							&IOData[ PSCR_PROLOGUE_LENGTH ], 
							*pBufferLength 
							);
					}

⌨️ 快捷键说明

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