📄 pscrcmd.c
字号:
/*++
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 + -