/***************************************************************************** @doc INT EXT ****************************************************************************** * $ProjectName: $ * $ProjectRevision: $ *----------------------------------------------------------------------------- * $Source: z:/pr/cmeu0/sw/sccmusbm.ms/rcs/scusbcb.c $ * $Revision: 1.9 $ *----------------------------------------------------------------------------- * $Author: WFrischauf $ *----------------------------------------------------------------------------- * History: see EOF *----------------------------------------------------------------------------- * * Copyright © 2000 OMNIKEY AG ******************************************************************************/ #include "wdm.h" #include "stdarg.h" #include "stdio.h" #include "usbdi.h" #include "usbdlib.h" #include "sccmusbm.h" ULONG dataRatesSupported[] = { 9600, 19200, 38400, 76800, 115200}; ULONG CLKFrequenciesSupported[] = {3571}; /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_StartCardTracking( IN PDEVICE_OBJECT DeviceObject ) { NTSTATUS NTStatus; HANDLE hThread; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; // settings for thread synchronization SmartcardExtension->ReaderExtension->TimeToTerminateThread = FALSE; SmartcardExtension->ReaderExtension->fThreadTerminated = FALSE; SmartcardDebug(DEBUG_TRACE, ("%s!StartCardTracking: Enter\n",DRIVER_NAME)); KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); // create thread for updating current state NTStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, CMUSB_UpdateCurrentStateThread, DeviceObject); if (!NT_ERROR(NTStatus)) { // // We've got the thread. Now get a pointer to it. // NTStatus = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, &SmartcardExtension->ReaderExtension->ThreadObjectPointer, NULL); if (NT_ERROR(NTStatus)) { SmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE; } else { // // Now that we have a reference to the thread // we can simply close the handle. // ZwClose(hThread); } } SmartcardDebug(DEBUG_DRIVER, ("%s!StartCardTracking: -----------------------------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!StartCardTracking: STARTING THREAD\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!StartCardTracking: -----------------------------------------------------------\n",DRIVER_NAME)); KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex, FALSE); SmartcardDebug(DEBUG_TRACE, ("%s!StartCardTracking: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID CMUSB_StopCardTracking( IN PDEVICE_OBJECT DeviceObject ) { PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; SmartcardDebug(DEBUG_TRACE, ("%s!StopCardTracking: Enter\n",DRIVER_NAME)); DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; if (SmartcardExtension->ReaderExtension->fThreadTerminated == FALSE) { SmartcardDebug(DEBUG_DRIVER, ("%s!StopCardTracking: waiting for mutex\n",DRIVER_NAME)); // kill thread KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); SmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE; KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE); KeWaitForSingleObject(SmartcardExtension->ReaderExtension->ThreadObjectPointer, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(SmartcardExtension->ReaderExtension->ThreadObjectPointer); } SmartcardDebug(DEBUG_TRACE, ("%s!StopCardTracking: Exit\n",DRIVER_NAME)); } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID CMUSB_UpdateCurrentStateThread( IN PVOID Context ) { PDEVICE_OBJECT DeviceObject = Context; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; NTSTATUS NTStatus,DebugStatus; ULONG ulInterval; DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; KeWaitForSingleObject(&DeviceExtension->CanRunUpdateThread, Executive, KernelMode, FALSE, NULL); SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread started\n",DRIVER_NAME)); do { // every 500 ms the s NTStatus request is sent ulInterval = 500; KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); if ( SmartcardExtension->ReaderExtension->TimeToTerminateThread ) { SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: -----------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: STOPPING THREAD\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: -----------------------------------------\n",DRIVER_NAME)); KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE); SmartcardExtension->ReaderExtension->fThreadTerminated = TRUE; PsTerminateSystemThread( STATUS_SUCCESS ); } NTStatus = CMUSB_UpdateCurrentState (DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { SmartcardDebug(DEBUG_DRIVER, ("%s!setting update interval to 1ms\n",DRIVER_NAME)); ulInterval = 1; } else if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_DRIVER, ("%s!NO STATUS RECEIVED\n",DRIVER_NAME)); } KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE); CMUSB_Wait (ulInterval); } while (TRUE); } NTSTATUS CMUSB_UpdateCurrentState( IN PDEVICE_OBJECT DeviceObject ) { NTSTATUS NTStatus; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; BOOLEAN fCardStateChanged = FALSE; ULONG ulBytesRead; KIRQL irql; DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(DeviceObject, 0x20, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus == STATUS_SUCCESS) { SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadP1(DeviceObject); ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; if (NTStatus == STATUS_SUCCESS && ulBytesRead == 1) { /* we got the NTStatus information */ if ((SmartcardExtension->SmartcardReply.Buffer[0] & 0x40) == 0x40) { if ((SmartcardExtension->SmartcardReply.Buffer[0] & 0x80) == 0x80) { SmartcardExtension->ReaderExtension->ulNewCardState = POWERED; } else { SmartcardExtension->ReaderExtension->ulNewCardState = INSERTED; } } else { SmartcardExtension->ReaderExtension->ulNewCardState = REMOVED; } KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); if (SmartcardExtension->ReaderExtension->ulNewCardState == INSERTED && SmartcardExtension->ReaderExtension->ulOldCardState == POWERED ) { // card has been removed and reinserted SmartcardExtension->ReaderExtension->ulNewCardState = REMOVED; } if (SmartcardExtension->ReaderExtension->ulNewCardState == INSERTED && (SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN || SmartcardExtension->ReaderExtension->ulOldCardState == REMOVED )) { // card has been inserted SmartcardDebug(DEBUG_DRIVER,( "%s!UpdateCurrentStateThread Smartcard inserted\n",DRIVER_NAME)); fCardStateChanged = TRUE; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; } // state after reset of the PC if (SmartcardExtension->ReaderExtension->ulNewCardState == POWERED && SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN ) { // card has been inserted SmartcardDebug(DEBUG_DRIVER,( "%s!UpdateCurrentStateThread Smartcard inserted (and powered)\n",DRIVER_NAME)); fCardStateChanged = TRUE; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; } if (SmartcardExtension->ReaderExtension->ulNewCardState == REMOVED && (SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN || SmartcardExtension->ReaderExtension->ulOldCardState == INSERTED || SmartcardExtension->ReaderExtension->ulOldCardState == POWERED ) ) { // card has been removed fCardStateChanged = TRUE; SmartcardDebug(DEBUG_DRIVER,( "%s!UpdateCurrentStateThread Smartcard removed\n",DRIVER_NAME)); SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; SmartcardExtension->CardCapabilities.ATR.Length = 0; RtlFillMemory((PVOID)&SmartcardExtension->ReaderExtension->CardParameters, sizeof(CARD_PARAMETERS), 0x00); } KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); // complete IOCTL_SMARTCARD_IS_ABSENT or IOCTL_SMARTCARD_IS_PRESENT if (fCardStateChanged == TRUE && SmartcardExtension->OsData->NotificationIrp != NULL) { SmartcardDebug(DEBUG_DRIVER,("%s!UpdateCurrentStateThread: completing IRP\n",DRIVER_NAME)); CMUSB_CompleteCardTracking(SmartcardExtension); } // save old state SmartcardExtension->ReaderExtension->ulOldCardState = SmartcardExtension->ReaderExtension->ulNewCardState; } } return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID CMUSB_CompleteCardTracking( IN PSMARTCARD_EXTENSION SmartcardExtension ) { KIRQL ioIrql, keIrql; PIRP notificationIrp; IoAcquireCancelSpinLock(&ioIrql); KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &keIrql); notificationIrp = SmartcardExtension->OsData->NotificationIrp; SmartcardExtension->OsData->NotificationIrp = NULL; KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, keIrql); if (notificationIrp) { IoSetCancelRoutine(notificationIrp,NULL); } IoReleaseCancelSpinLock(ioIrql); if (notificationIrp) { SmartcardDebug(DEBUG_DRIVER, ("%s!CompleteCardTracking: Completing NotificationIrp %lxh\n",DRIVER_NAME,notificationIrp)); // finish the request if (notificationIrp->Cancel) { notificationIrp->IoStatus.Status = STATUS_CANCELLED; } else { notificationIrp->IoStatus.Status = STATUS_SUCCESS; } notificationIrp->IoStatus.Information = 0; IoCompleteRequest(notificationIrp, IO_NO_INCREMENT); } } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_Wait (ULONG ulMilliseconds) { NTSTATUS NTStatus = STATUS_SUCCESS; LARGE_INTEGER WaitTime; // -10000 indicates 1ms relativ WaitTime = RtlConvertLongToLargeInteger(ulMilliseconds * -10000); KeDelayExecutionThread(KernelMode,FALSE,&WaitTime); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_CreateClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS NTStatus = STATUS_SUCCESS; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); SmartcardDebug(DEBUG_TRACE, ("%s!CreateClose: Enter\n",DRIVER_NAME)); DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; // // dispatch major function // switch (IrpStack->MajorFunction) { case IRP_MJ_CREATE: SmartcardDebug(DEBUG_DRIVER, ("%s!CreateClose: IRP_MJ_CREATE\n",DRIVER_NAME)); if (DeviceExtension->RemoveDeviceRequested) { NTStatus = STATUS_DEVICE_BUSY; } else { if (InterlockedIncrement(&DeviceExtension->lOpenCount) > 1) { InterlockedDecrement(&DeviceExtension->lOpenCount); NTStatus = STATUS_ACCESS_DENIED; } } break; case IRP_MJ_CLOSE: SmartcardDebug(DEBUG_DRIVER, ("%s!CreateClose: IRP_MJ_CLOSE\n",DRIVER_NAME)); if (InterlockedDecrement(&DeviceExtension->lOpenCount) < 0) { InterlockedIncrement(&DeviceExtension->lOpenCount); } // check if the device has been removed // if so free the resources if (DeviceExtension->DeviceRemoved == TRUE) { SmartcardDebug(DEBUG_DRIVER, ("%s!CreateClose: freeing resources\n",DRIVER_NAME)); if (DeviceExtension->fPnPResourceManager == FALSE) { // // Free all allocated buffer // ExFreePool(DeviceExtension->DosDeviceName.Buffer); } ExFreePool(SmartcardExtension->ReaderExtension); SmartcardExtension->ReaderExtension = NULL; // // Let the lib free the send/receive buffers // SmartcardExit(SmartcardExtension); } break; default: // // unrecognized command // NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Information = 0; Irp->IoStatus.Status = NTStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); SmartcardDebug(DEBUG_TRACE, ("%s!CreateClose: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_Transmit( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; //this seems to make problems in Windows 98 //KeSetPriorityThread(KeGetCurrentThread(),HIGH_PRIORITY); switch (SmartcardExtension->CardCapabilities.Protocol.Selected) { case SCARD_PROTOCOL_RAW: NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; case SCARD_PROTOCOL_T0: NTStatus = CMUSB_TransmitT0(SmartcardExtension); break; case SCARD_PROTOCOL_T1: NTStatus = CMUSB_TransmitT1(SmartcardExtension); break; default: NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; } //KeSetPriorityThread(KeGetCurrentThread(),LOW_REALTIME_PRIORITY); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_ResetT0ReadBuffer( PSMARTCARD_EXTENSION SmartcardExtension ) { SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByte = -1; SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByteRead = -1; return STATUS_SUCCESS; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_ReadT0( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; NTSTATUS DebugStatus; LONG lBytesToRead; LONG lBytesRead; LONG lLastByte; LONG lLastByteRead; PDEVICE_EXTENSION DeviceExtension; PUSBD_PIPE_INFORMATION pipeHandle = NULL; PUSBD_INTERFACE_INFORMATION interface; SmartcardDebug(DEBUG_TRACE, ("%s!ReadT0: Enter\n",DRIVER_NAME)); DeviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension; interface = DeviceExtension->UsbInterface; pipeHandle = &interface->Pipes[0]; lBytesToRead = (LONG)SmartcardExtension->SmartcardReply.BufferLength; lLastByte = SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByte; lLastByteRead = SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByteRead; // check if further bytes must be read from pipe 1 while (lLastByteRead + lBytesToRead > lLastByte) { SmartcardExtension->SmartcardReply.BufferLength = 1; SmartcardExtension->ReaderExtension->ulTimeoutP1 = 1000 + (ULONG)((SmartcardExtension->CardCapabilities.T0.WT/1000) * lBytesToRead); NTStatus = CMUSB_ReadP1(SmartcardExtension->OsData->DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitReadT0; } else if (NTStatus != STATUS_SUCCESS) { goto ExitReadT0; } lBytesRead = (LONG)SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(SmartcardExtension->ReaderExtension->T0ReadBuffer + (lLastByte +1)), (PVOID)SmartcardExtension->SmartcardReply.Buffer, lBytesRead); lLastByte += lBytesRead; } // end of while // copy bytes SmartcardExtension->SmartcardReply.BufferLength = lBytesToRead; RtlCopyBytes ((PVOID)SmartcardExtension->SmartcardReply.Buffer, (PVOID)(SmartcardExtension->ReaderExtension->T0ReadBuffer + (lLastByteRead +1)), lBytesToRead); lLastByteRead += lBytesToRead; /* SmartcardDebug(DEBUG_TRACE, ("%s!lBytesToRead=%ld lLastByte=%ld lLastByteRead=%ld\n", DRIVER_NAME, lBytesToRead, lLastByte, lLastByteRead) ); */ SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByte = lLastByte; SmartcardExtension->ReaderExtension->T0ReadBuffer_OffsetLastByteRead = lLastByteRead; SmartcardDebug(DEBUG_TRACE, ("%s!ReadT0: Exit %lx\n",DRIVER_NAME,NTStatus)); ExitReadT0: return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ #define T0_HEADER_LEN 0x05 #define T0_STATE_LEN 0x02 #define TIMEOUT_CANCEL_READ_P1 30000 NTSTATUS CMUSB_TransmitT0( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; NTSTATUS DebugStatus; UCHAR bWriteBuffer[CMUSB_BUFFER_SIZE]; UCHAR bReadBuffer [CMUSB_BUFFER_SIZE]; ULONG ulWriteBufferOffset; ULONG ulReadBufferOffset; ULONG ulBytesToWrite; ULONG ulBytesToRead; ULONG ulBytesToWriteThisStep; ULONG ulBytesToReadThisStep; ULONG ulBytesStillToWrite; ULONG ulBytesRead; ULONG ulBytesStillToRead; BOOLEAN fDataDirectionFromCard; BYTE bProcedureByte; BYTE bINS; BOOLEAN fT0TransferToCard; BOOLEAN fT0TransferFromCard; BOOLEAN fSW1SW2Sent; ULONG ulUsedCWT; UCHAR bUsedCWTHi; LARGE_INTEGER liTimeout; PDEVICE_EXTENSION DeviceExtension; UCHAR bTmp; ULONG i; PUSBD_PIPE_INFORMATION pipeHandle = NULL; PUSBD_INTERFACE_INFORMATION interface; SmartcardDebug(DEBUG_TRACE, ("%s!TransmitT0 : Enter\n",DRIVER_NAME)); fT0TransferToCard = FALSE; fT0TransferFromCard = FALSE; fSW1SW2Sent = FALSE; // resync CardManUSB by reading the NTStatus byte SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x20, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitTransmitT0; } SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadP1(SmartcardExtension->OsData->DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitTransmitT0; } else if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitTransmitT0; } DeviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension; interface = DeviceExtension->UsbInterface; pipeHandle = &interface->Pipes[0]; SmartcardExtension->ReaderExtension->ulTimeoutP1 = (ULONG)(SmartcardExtension->CardCapabilities.T0.WT/1000); // // Let the lib build a T=0 packet // SmartcardExtension->SmartcardRequest.BufferLength = 0; // no bytes additionally needed NTStatus = SmartcardT0Request(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { // // This lib detected an error in the data to send. // goto ExitTransmitT0; } ulBytesStillToWrite = ulBytesToWrite = T0_HEADER_LEN + SmartcardExtension->T0.Lc; ulBytesStillToRead = ulBytesToRead = SmartcardExtension->T0.Le; if (SmartcardExtension->T0.Lc) fT0TransferToCard = TRUE; if (SmartcardExtension->T0.Le) fT0TransferFromCard = TRUE; // ---------------------------- // smart card ==> CardMan USB // ---------------------------- if (fT0TransferFromCard) { SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: MODE 3\n",DRIVER_NAME)); // granularity 256 ms ulUsedCWT = (ULONG)(SmartcardExtension->CardCapabilities.T0.WT/1000); SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: ulUsedCWT= %ld\n",DRIVER_NAME,ulUsedCWT)); bUsedCWTHi = (UCHAR)(((ulUsedCWT & 0x0000FF00)>>8) + 1 + 5) ; // copy data to the write buffer SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: CLA = %x INS = %x P1 = %x P2 = %x L = %x\n", DRIVER_NAME, SmartcardExtension->SmartcardRequest.Buffer[0], SmartcardExtension->SmartcardRequest.Buffer[1], SmartcardExtension->SmartcardRequest.Buffer[2], SmartcardExtension->SmartcardRequest.Buffer[3], SmartcardExtension->SmartcardRequest.Buffer[4])); RtlCopyBytes((PVOID)bWriteBuffer, (PVOID)SmartcardExtension->SmartcardRequest.Buffer, ulBytesToWrite); bINS = bWriteBuffer[1]; ulWriteBufferOffset = 0; ulReadBufferOffset = 0; // STEP 1 : write CLA INS P1 P2 Lc ulBytesToWriteThisStep = 5; RtlCopyBytes((PVOID)(SmartcardExtension->SmartcardRequest.Buffer), (PVOID)(bWriteBuffer+ulWriteBufferOffset), ulBytesToWriteThisStep); if (SmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { CMUSB_InverseBuffer(SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferLength); } SmartcardExtension->SmartcardReply.BufferLength = 512; NTStatus = CMUSB_ReadP1_T0(SmartcardExtension->OsData->DeviceObject); if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: CMUSB_ReadP1_T0 returned = %x\n",DRIVER_NAME,NTStatus)); goto ExitTransmitT0; } SmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWriteThisStep; NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x03, // mode 3 bUsedCWTHi, //bValueLo, 0x00, //bValueHi, (UCHAR)(ulBytesToRead%256), //bIndexLo, (UCHAR)(SmartcardExtension->SmartcardRequest.Buffer[1]) //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: CMUSB_WriteP0 returned %x\n",DRIVER_NAME,NTStatus)); goto ExitTransmitT0; } liTimeout = RtlConvertLongToLargeInteger(TIMEOUT_CANCEL_READ_P1 * -10000); SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: waiting for P1 event\n",DRIVER_NAME,NTStatus)); NTStatus = KeWaitForSingleObject(&DeviceExtension->ReadP1Completed, Executive, KernelMode, FALSE, &liTimeout); // ----------------------------- // check if P1 has been stalled // ----------------------------- if (SmartcardExtension->ReaderExtension->fP1Stalled == TRUE) { SmartcardDebug(DEBUG_PROTOCOL, ("%s!STransmitT0: TATUS_DEVICE_DATA_ERROR\n",DRIVER_NAME)); NTStatus = STATUS_DEVICE_DATA_ERROR; // P1 has been stalled ==> we must reset the pipe and send a NTStatus to enable it again DebugStatus = CMUSB_ResetPipe(SmartcardExtension->OsData->DeviceObject, pipeHandle); DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); SmartcardExtension->SmartcardReply.BufferLength = 0; goto ExitTransmitT0; } // ------------------------------- // check if a timeout has occured // ------------------------------- else if (NTStatus == STATUS_TIMEOUT) { // probably the smart card does not work // cancel T0 read operation by sending any P0 command SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: cancelling read operation\n",DRIVER_NAME)); SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x20, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); NTStatus = STATUS_IO_TIMEOUT; goto ExitTransmitT0; } // ------------------------------------------- // check if at least 9 bytes have been sent // ------------------------------------------- else if (SmartcardExtension->SmartcardReply.BufferLength < 9) { NTStatus = STATUS_UNSUCCESSFUL; goto ExitTransmitT0; } else { #if DBG SmartcardDebug(DEBUG_PROTOCOL, ("%s!<==[P1] ",DRIVER_NAME)); for (i=0;i< SmartcardExtension->SmartcardReply.BufferLength;i++) { bTmp = SmartcardExtension->SmartcardReply.Buffer[i]; if (SmartcardExtension->ReaderExtension->fInverseAtr && SmartcardExtension->ReaderExtension->ulTimeoutP1 != DEFAULT_TIMEOUT_P1) { //CMUSB_InverseBuffer(&bTmp,1); SmartcardDebug(DEBUG_PROTOCOL,("%x ",bTmp)); } else { SmartcardDebug(DEBUG_PROTOCOL,("%x ",bTmp)); } } SmartcardDebug(DEBUG_PROTOCOL, ("(%ld)\n",SmartcardExtension->SmartcardReply.BufferLength)); #endif // ignore the first 8 dummy bytes SmartcardExtension->SmartcardReply.BufferLength -= 8; RtlCopyBytes((PVOID)(bReadBuffer), (PVOID)(SmartcardExtension->SmartcardReply.Buffer+8), SmartcardExtension->SmartcardReply.BufferLength); RtlCopyBytes((PVOID)(SmartcardExtension->SmartcardReply.Buffer), (PVOID)(bReadBuffer), SmartcardExtension->SmartcardReply.BufferLength); if (SmartcardExtension->ReaderExtension->fInverseAtr) { CMUSB_InverseBuffer(SmartcardExtension->SmartcardReply.Buffer, SmartcardExtension->SmartcardReply.BufferLength); } } } // ----------------------------- // CardMan USB ==> smart card or // no transfer // ----------------------------- else { SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: MODE 2\n",DRIVER_NAME)); // copy data to the write buffer SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: CLA = %x INS = %x P1 = %x P2 = %X L = %x\n",DRIVER_NAME, SmartcardExtension->SmartcardRequest.Buffer[0], SmartcardExtension->SmartcardRequest.Buffer[1], SmartcardExtension->SmartcardRequest.Buffer[2], SmartcardExtension->SmartcardRequest.Buffer[3], SmartcardExtension->SmartcardRequest.Buffer[4])); RtlCopyBytes((PVOID)bWriteBuffer, (PVOID)SmartcardExtension->SmartcardRequest.Buffer, ulBytesToWrite); // SendingToCard: ulWriteBufferOffset = 0; ulReadBufferOffset = 0; bINS = bWriteBuffer[1]; // STEP 1 : write CLA INS P1 P2 Lc ulBytesToWriteThisStep = 5; RtlCopyBytes((PVOID)(SmartcardExtension->SmartcardRequest.Buffer), (PVOID)(bWriteBuffer+ulWriteBufferOffset), ulBytesToWriteThisStep); SmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWriteThisStep; if (SmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { CMUSB_InverseBuffer(SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferLength); } NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x02, //T=0 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; NTStatus = CMUSB_ResetT0ReadBuffer(SmartcardExtension); // STEP 2 : read procedure byte do { do { SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadT0(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; bProcedureByte = SmartcardExtension->SmartcardReply.Buffer[0]; if (SmartcardExtension->ReaderExtension->fInverseAtr) { CMUSB_InverseBuffer(&bProcedureByte,1); } SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT0: procedure byte = %x\n", DRIVER_NAME, bProcedureByte)); if (bProcedureByte == 0x60) { // wait work waitung time; // we just try to read again } } while (bProcedureByte == 0x60); // check for ACK if ((bProcedureByte & 0xFE) == (bINS & 0xFE) ) { ulBytesToWriteThisStep = ulBytesStillToWrite; if (ulBytesToWriteThisStep > 0) { // at least one byte must be sent to the card RtlCopyBytes((PVOID)(SmartcardExtension->SmartcardRequest.Buffer), (PVOID)(bWriteBuffer+ulWriteBufferOffset), ulBytesToWriteThisStep); SmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWriteThisStep; if (SmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { CMUSB_InverseBuffer(SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferLength); } NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x02, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; } } // check for NAK else if ( (~bProcedureByte & 0xFE) == (bINS & 0xFE)) { ulBytesToWriteThisStep = 1; RtlCopyBytes((PVOID)SmartcardExtension->SmartcardRequest.Buffer, (PVOID)(bWriteBuffer+ulWriteBufferOffset), ulBytesToWriteThisStep); SmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWriteThisStep; if (SmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { CMUSB_InverseBuffer(SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferLength); } NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x02, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; } // check for SW1 else if ( (bProcedureByte > 0x60 && bProcedureByte <= 0x6F) || (bProcedureByte >= 0x90 && bProcedureByte <= 0x9F) ) { bReadBuffer[ulReadBufferOffset] = SmartcardExtension->SmartcardReply.Buffer[0]; ulReadBufferOffset++; SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadT0(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(bReadBuffer + ulReadBufferOffset), (PVOID)(SmartcardExtension->SmartcardReply.Buffer), SmartcardExtension->SmartcardReply.BufferLength); ulReadBufferOffset += ulBytesRead; fSW1SW2Sent = TRUE; } else { NTStatus = STATUS_UNSUCCESSFUL; goto ExitTransmitT0; } }while (!fSW1SW2Sent); if (SmartcardExtension->ReaderExtension->fInverseAtr) { CMUSB_InverseBuffer(bReadBuffer, ulReadBufferOffset); } // copy received bytes RtlCopyBytes((PVOID)SmartcardExtension->SmartcardReply.Buffer, (PVOID)bReadBuffer, ulReadBufferOffset); SmartcardExtension->SmartcardReply.BufferLength = ulReadBufferOffset; } // let the lib copy the received bytes to the user buffer NTStatus = SmartcardT0Reply(SmartcardExtension); ExitTransmitT0: // ------------------------------------------ // ITSEC E2 requirements: clear write buffers // ------------------------------------------ RtlFillMemory((PVOID)bWriteBuffer,sizeof(bWriteBuffer),0x00); RtlFillMemory((PVOID)SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferSize,0x00); SmartcardDebug(DEBUG_TRACE, ("%s!TransmitT0 : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } #undef T0_HEADER_LEN #undef T0_STATE_LEN #undef TIMEOUT_CANCEL_READ_P1 /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_TransmitT1( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; NTSTATUS DebugStatus; ULONG ulBytesToRead; ULONG ulCurrentWaitTime; ULONG ulWTXWaitTime; LARGE_INTEGER waitTime; BOOLEAN fStateTimer; ULONG ulTemp; PDEVICE_EXTENSION DeviceExtension; PUSBD_INTERFACE_INFORMATION interface; PUSBD_PIPE_INFORMATION pipeHandle = NULL; BOOLEAN fCancelTimer = FALSE; BYTE bTemp; BYTE bMultiplier; SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1: CWT = %ld(ms)\n",DRIVER_NAME, SmartcardExtension->CardCapabilities.T1.CWT/1000)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1: BWT = %ld(ms)\n",DRIVER_NAME, SmartcardExtension->CardCapabilities.T1.BWT/1000)); DeviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension; interface = DeviceExtension->UsbInterface; pipeHandle = &interface->Pipes[0]; ulCurrentWaitTime = (ULONG)(1000 + SmartcardExtension->CardCapabilities.T1.BWT/1000); ulWTXWaitTime = 0; do { SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = SmartcardT1Request(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { // this should never happen, so we return immediately goto ExitTransmitT1; } NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x01, //T=1 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) break; // there must be severe error if (ulWTXWaitTime == 0 ) { // use BWT waitTime = RtlConvertLongToLargeInteger(ulCurrentWaitTime * -10000); } else { // use WTX time waitTime = RtlConvertLongToLargeInteger(ulWTXWaitTime * -10000); } KeSetTimer(&SmartcardExtension->ReaderExtension->WaitTimer, waitTime, NULL); // timer is now in the queue fCancelTimer = TRUE; ulTemp = 0; do { NTStatus = CMUSB_ReadP1(SmartcardExtension->OsData->DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitTransmitT1; } fStateTimer = KeReadStateTimer(&SmartcardExtension->ReaderExtension->WaitTimer); if (fStateTimer == TRUE) { // timer has been removed from the queue fCancelTimer = FALSE; SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1: T1 card does not respond in time\n",DRIVER_NAME)); NTStatus = STATUS_IO_TIMEOUT; break; } if (SmartcardExtension->SmartcardReply.Buffer[0] >= 3) { if (SmartcardExtension->SmartcardReply.Buffer[1] > ulTemp) { // restart CWT for 32 bytes ulCurrentWaitTime = (ULONG)(100 + 32*(SmartcardExtension->CardCapabilities.T1.CWT/1000)); waitTime = RtlConvertLongToLargeInteger(ulCurrentWaitTime * -10000); KeSetTimer(&SmartcardExtension->ReaderExtension->WaitTimer, waitTime, NULL); // timer is in the queue fCancelTimer = TRUE; ulTemp = SmartcardExtension->SmartcardReply.Buffer[1]; } else { // CardMan USB has not received further bytes // do nothing } } } while (SmartcardExtension->SmartcardReply.Buffer[0] < 3 || (SmartcardExtension->SmartcardReply.Buffer[0] != SmartcardExtension->SmartcardReply.Buffer[1] + 4 ) ); // cancel timer now if (fCancelTimer == TRUE) { fCancelTimer = FALSE; KeCancelTimer(&SmartcardExtension->ReaderExtension->WaitTimer); // timer is removed from the queue } if (NTStatus != STATUS_SUCCESS) { SmartcardExtension->SmartcardReply.BufferLength = 0L; } else { ulBytesToRead = SmartcardExtension->SmartcardReply.Buffer[0]; SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.Buffer[0]; NTStatus = CMUSB_ReadP0(SmartcardExtension->OsData->DeviceObject); } bTemp = SmartcardExtension->SmartcardReply.Buffer[1]; bMultiplier = SmartcardExtension->SmartcardReply.Buffer[3]; if (SmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { CMUSB_InverseBuffer(&bTemp,1); CMUSB_InverseBuffer(&bMultiplier,1); } if (bTemp == T1_WTX_REQUEST) { SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1: T1_WTX_REQUEST received\n",DRIVER_NAME)); ulWTXWaitTime = (ULONG)(1000 + bMultiplier * (SmartcardExtension->CardCapabilities.T1.BWT/1000)); } else { ulWTXWaitTime = 0; } // bug fix for smclib if (SmartcardExtension->T1.State == T1_IFS_RESPONSE && SmartcardExtension->T1.OriginalState == T1_I_BLOCK) { SmartcardExtension->T1.State = T1_I_BLOCK; } NTStatus = SmartcardT1Reply(SmartcardExtension); } while (NTStatus == STATUS_MORE_PROCESSING_REQUIRED); ExitTransmitT1: // ------------------------------------------ // ITSEC E2 requirements: clear write buffers // ------------------------------------------ RtlFillMemory((PVOID)SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferSize,0x00); // timer will be cancelled here if there was an error if (fCancelTimer == TRUE) { KeCancelTimer(&SmartcardExtension->ReaderExtension->WaitTimer); // timer is removed from the queue } return NTStatus; } /***************************************************************************** Routine Description: This function sets the desired protocol . If necessary a PTS is performed Arguments: pointer to SMARTCARD_EXTENSION Return Value: NT NTStatus *****************************************************************************/ NTSTATUS CMUSB_SetProtocol( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; NTSTATUS DebugStatus; ULONG ulNewProtocol; UCHAR abPTSRequest[4]; UCHAR abReadBuffer[6]; UCHAR abPTSReply [4]; ULONG ulBytesRead; LARGE_INTEGER liWaitTime; BOOLEAN fStateTimer; ULONG ulWaitTime; PDEVICE_EXTENSION DeviceExtension; PUSBD_PIPE_INFORMATION pipeHandle = NULL; PUSBD_INTERFACE_INFORMATION interface; UCHAR bTemp; BOOLEAN fCancelTimer = FALSE; KIRQL irql; SmartcardDebug(DEBUG_TRACE, ("%s!SetProtocol : Enter\n",DRIVER_NAME)); DeviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension; interface = DeviceExtension->UsbInterface; pipeHandle = &interface->Pipes[0]; // // Check if the card is already in specific state // and if the caller wants to have the already selected protocol. // We return success if this is the case. // if ((SmartcardExtension->CardCapabilities.Protocol.Selected & SmartcardExtension->MinorIoControlCode)) { NTStatus = STATUS_SUCCESS; goto ExitSetProtocol; } ulNewProtocol = SmartcardExtension->MinorIoControlCode; while (TRUE) { // set initial character of PTS abPTSRequest[0] = 0xFF; // set the format character if (SmartcardExtension->CardCapabilities.Protocol.Supported & ulNewProtocol & SCARD_PROTOCOL_T1) { // select T=1 and indicate that PTS1 follows abPTSRequest[1] = 0x11; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1; } else if (SmartcardExtension->CardCapabilities.Protocol.Supported & ulNewProtocol & SCARD_PROTOCOL_T0) { // select T=1 and indicate that PTS1 follows abPTSRequest[1] = 0x10; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; } else { NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetProtocol; } // CardMan USB support higher baudrates only for T=1 // ==> Dl=1 if (abPTSRequest[1] == 0x10) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1 for T=0\n",DRIVER_NAME)); SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; } // set pts1 which codes Fl and Dl bTemp = (BYTE) (SmartcardExtension->CardCapabilities.PtsData.Fl << 4 | SmartcardExtension->CardCapabilities.PtsData.Dl); switch (bTemp) { case 0x11: case 0x12: case 0x13: case 0x14: case 0x18: case 0x91: case 0x92: case 0x93: case 0x94: case 0x98: // do nothing // we support these Fl/Dl parameters break ; default: SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; bTemp = (BYTE) (SmartcardExtension->CardCapabilities.PtsData.Fl << 4 | SmartcardExtension->CardCapabilities.PtsData.Dl); break; } abPTSRequest[2] = bTemp; // set pck (check character) abPTSRequest[3] = (BYTE)(abPTSRequest[0] ^ abPTSRequest[1] ^ abPTSRequest[2]); SmartcardDebug(DEBUG_PROTOCOL, ("%s! writing PTS request\n",DRIVER_NAME)); RtlCopyBytes((PVOID)SmartcardExtension->SmartcardRequest.Buffer, (PVOID)abPTSRequest, 4); SmartcardExtension->SmartcardRequest.BufferLength = 4; NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x01, //we can use T=1 setting for direct communication 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00); //bIndexHi, if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR, ("%s! writing PTS request failed\n",DRIVER_NAME)); goto ExitSetProtocol; } // read back pts data SmartcardDebug(DEBUG_PROTOCOL, ("%s! reading PTS reply\n",DRIVER_NAME)); // maximim initial waiting time is 9600 * etu // => 1 sec is sufficient ulWaitTime = 1000; liWaitTime = RtlConvertLongToLargeInteger(ulWaitTime * -10000); KeSetTimer(&SmartcardExtension->ReaderExtension->WaitTimer, liWaitTime, NULL); // timer is now in the queue fCancelTimer = TRUE; do { SmartcardExtension->ReaderExtension->ulTimeoutP1 = ulWaitTime; DebugStatus = CMUSB_ReadP1(SmartcardExtension->OsData->DeviceObject); // ----------------------------- // check if P1 has been stalled // ----------------------------- if (SmartcardExtension->ReaderExtension->fP1Stalled == TRUE) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); SmartcardExtension->SmartcardReply.BufferLength = 0; goto ExitSetProtocol; } fStateTimer = KeReadStateTimer(&SmartcardExtension->ReaderExtension->WaitTimer); if (fStateTimer == TRUE) { // timer has timed out and has been removed from the queue fCancelTimer = FALSE; SmartcardDebug(DEBUG_PROTOCOL, ("%s! Timeout while PTS reply\n",DRIVER_NAME)); NTStatus = STATUS_IO_TIMEOUT; break; } } while (SmartcardExtension->SmartcardReply.Buffer[0] < 4 ); if (fCancelTimer == TRUE) { fCancelTimer = FALSE; // timer is still in the queue, remove it KeCancelTimer(&SmartcardExtension->ReaderExtension->WaitTimer); } if (NTStatus == STATUS_IO_TIMEOUT) { if (SmartcardExtension->SmartcardReply.Buffer[0] == 3) { SmartcardExtension->SmartcardReply.BufferLength = 3; } else { if (SmartcardExtension->CardCapabilities.PtsData.Type != PTS_TYPE_DEFAULT) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS failed : Trying default parameters\n",DRIVER_NAME)); // the card did either not reply or it replied incorrectly // so try default values SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT; SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; NTStatus = CMUSB_CardPower(SmartcardExtension); continue; } goto ExitSetProtocol; } } else { SmartcardExtension->SmartcardReply.BufferLength = 4; } NTStatus = CMUSB_ReadP0(SmartcardExtension->OsData->DeviceObject); ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; if (NTStatus != STATUS_SUCCESS || !(ulBytesRead == 4 || ulBytesRead == 3)) { SmartcardDebug(DEBUG_ERROR, ("%s! reading PTS reply failed\n",DRIVER_NAME)); goto ExitSetProtocol; } RtlCopyBytes((PVOID)abPTSReply, (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); if (ulBytesRead == 4 && abPTSReply[0] == abPTSRequest[0] && abPTSReply[1] == abPTSRequest[1] && abPTSReply[2] == abPTSRequest[2] && abPTSReply[3] == abPTSRequest[3] ) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS request and reply match\n",DRIVER_NAME)); NTStatus = STATUS_SUCCESS; switch (abPTSRequest[2]) { // Fl/Dl case 0x11: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_9600; break ; case 0x12: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_19200; break ; case 0x13: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_38400; break ; case 0x14: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_76800; break ; case 0x18: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_115200; break ; case 0x91: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_9600; break ; case 0x92: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_19200; break ; case 0x93: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_38400; break ; case 0x94: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_76800; break ; case 0x98: SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_115200; break ; } break; } if (ulBytesRead == 3 && abPTSReply[0] == abPTSRequest[0] && (abPTSReply[1] & 0x7F) == (abPTSRequest[1] & 0x0F) && abPTSReply[2] == (BYTE)(abPTSReply[0] ^ abPTSReply[1] )) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! short PTS reply received\n",DRIVER_NAME)); NTStatus = STATUS_SUCCESS; if ((abPTSRequest[2] & 0x90) == 0x90) { SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_5_12MHZ + CMUSB_BAUDRATE_9600; } else { SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_9600; } break ; } if (SmartcardExtension->CardCapabilities.PtsData.Type != PTS_TYPE_DEFAULT) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS failed : Trying default parameters\n",DRIVER_NAME)); // the card did either not reply or it replied incorrectly // so try default values SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT; SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; NTStatus = CMUSB_CardPower(SmartcardExtension); continue; } // the card failed the pts request NTStatus = STATUS_DEVICE_PROTOCOL_ERROR; goto ExitSetProtocol; } ExitSetProtocol: switch (NTStatus) { case STATUS_IO_TIMEOUT: SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; *SmartcardExtension->IoRequest.Information = 0; break; case STATUS_SUCCESS: // now indicate that we're in specific mode KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); // return the selected protocol to the caller *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer = SmartcardExtension->CardCapabilities.Protocol.Selected; *SmartcardExtension->IoRequest.Information = sizeof(SmartcardExtension->CardCapabilities.Protocol.Selected); SmartcardDebug(DEBUG_PROTOCOL, ("%s! Selected protocol: T=%ld\n",DRIVER_NAME, SmartcardExtension->CardCapabilities.Protocol.Selected-1)); // ----------------------- // set parameters // ----------------------- if (SmartcardExtension->CardCapabilities.N != 0xff) { SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 2 + SmartcardExtension->CardCapabilities.N; } else { // N = 255 if (SmartcardExtension->CardCapabilities.Protocol.Selected & SCARD_PROTOCOL_T0) { // 12 etu for T=0; SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 2; } else { // 11 etu for T=1 SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 1; } } NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, SmartcardExtension->ReaderExtension->CardParameters.bCardType, SmartcardExtension->ReaderExtension->CardParameters.bBaudRate, SmartcardExtension->ReaderExtension->CardParameters.bStopBits); break; default : SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; *SmartcardExtension->IoRequest.Information = 0; break; } SmartcardDebug(DEBUG_TRACE, ("%s!SetProtocol : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_CardPower(IN PSMARTCARD_EXTENSION SmartcardExtension) { NTSTATUS NTStatus = STATUS_SUCCESS; NTSTATUS DebugStatus = STATUS_SUCCESS; UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength; KIRQL irql; #if DBG ULONG i; #endif; SmartcardDebug(DEBUG_TRACE, ("%s!CardPower: Enter\n",DRIVER_NAME)); #if DBG switch (SmartcardExtension->MinorIoControlCode) { case SCARD_WARM_RESET: SmartcardDebug(DEBUG_ATR, ("%s!CardPower: SCARD_WARM_RESTART\n",DRIVER_NAME)); break; case SCARD_COLD_RESET: SmartcardDebug(DEBUG_ATR, ("%s!CardPower: SCARD_COLD_RESTART\n",DRIVER_NAME)); break; case SCARD_POWER_DOWN: SmartcardDebug(DEBUG_ATR, ("%s!CardPower: SCARD_POWER_DOWN\n",DRIVER_NAME)); break; } #endif //DbgBreakPoint(); switch (SmartcardExtension->MinorIoControlCode) { case SCARD_WARM_RESET: case SCARD_COLD_RESET: // try asynchronous cards first // because some asynchronous cards // do not return 0xFF in the first byte NTStatus = CMUSB_PowerOnCard(SmartcardExtension, pbAtrBuffer, &ulAtrLength); if (NTStatus != STATUS_SUCCESS && NTStatus!= STATUS_NO_MEDIA) { NTStatus = CMUSB_PowerOnSynchronousCard(SmartcardExtension, pbAtrBuffer, &ulAtrLength); } if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } if (SmartcardExtension->ReaderExtension->fRawModeNecessary == FALSE) { // copy ATR to smart card structure // the lib needs the ATR for evaluation of the card parameters RtlCopyBytes((PVOID)SmartcardExtension->CardCapabilities.ATR.Buffer, (PVOID)pbAtrBuffer, ulAtrLength); SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength; KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE; KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; NTStatus = SmartcardUpdateCardCapabilities(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } // ----------------------- // set parameters // ----------------------- if (SmartcardExtension->CardCapabilities.N != 0xff) { // 0 <= N <= 254 SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 2 + SmartcardExtension->CardCapabilities.N; } else { // N = 255 if (SmartcardExtension->CardCapabilities.Protocol.Selected & SCARD_PROTOCOL_T0) { // 12 etu for T=0; SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 2; } else { // 11 etu for T=1 SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 1; } } NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, SmartcardExtension->ReaderExtension->CardParameters.bCardType, SmartcardExtension->ReaderExtension->CardParameters.bBaudRate, SmartcardExtension->ReaderExtension->CardParameters.bStopBits); #if DBG SmartcardDebug(DEBUG_ATR,("%s!CardPower: ATR : ",DRIVER_NAME)); for (i = 0;i < ulAtrLength;i++) SmartcardDebug(DEBUG_ATR,("%2.2x ",SmartcardExtension->CardCapabilities.ATR.Buffer[i])); SmartcardDebug(DEBUG_ATR,("\n")); #endif } else { SmartcardExtension->CardCapabilities.ATR.Buffer[0] = 0x3B; SmartcardExtension->CardCapabilities.ATR.Buffer[1] = 0x04; if (ulAtrLength > 62) { NTStatus = STATUS_DEVICE_PROTOCOL_ERROR; goto ExitCardPower; } RtlCopyBytes((PVOID)&SmartcardExtension->CardCapabilities.ATR.Buffer[2], (PVOID)pbAtrBuffer, ulAtrLength); ulAtrLength += 2; SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength; KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; NTStatus = SmartcardUpdateCardCapabilities(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } SmartcardDebug(DEBUG_ATR,("CardPower: ATR of synchronous smart card : %2.2x %2.2x %2.2x %2.2x\n", pbAtrBuffer[0],pbAtrBuffer[1],pbAtrBuffer[2],pbAtrBuffer[3])); // copied from serial CardMan //SmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE; } // copy ATR to user space if (SmartcardExtension->IoRequest.ReplyBufferLength >= SmartcardExtension->CardCapabilities.ATR.Length) { RtlCopyBytes((PVOID)SmartcardExtension->IoRequest.ReplyBuffer, (PVOID)SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->CardCapabilities.ATR.Length); *SmartcardExtension->IoRequest.Information = ulAtrLength; } else { // Called from SET_PROTOCOL, so we don't want to copy the ATR. } break; case SCARD_POWER_DOWN: NTStatus = CMUSB_PowerOffCard(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); break; } ExitCardPower: SmartcardDebug(DEBUG_TRACE, ("%s!CardPower: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_PowerOffCard ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; NTSTATUS DebugStatus; PDEVICE_OBJECT DeviceObject; ULONG ulBytesRead; SmartcardDebug(DEBUG_TRACE, ("%s!PowerOffCard: Enter\n",DRIVER_NAME)); DeviceObject = SmartcardExtension->OsData->DeviceObject; SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(DeviceObject, 0x11, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); // now read the NTStatus SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOff; } ExitPowerOff: // set card state for update thread // otherwise a card removal/insertion would be recognized if (SmartcardExtension->ReaderExtension->ulOldCardState == POWERED) SmartcardExtension->ReaderExtension->ulOldCardState = INSERTED; SmartcardDebug(DEBUG_TRACE, ("%s!PowerOffCard: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_ReadStateAfterP1Stalled( IN PDEVICE_OBJECT DeviceObject ) { NTSTATUS NTStatus; PSMARTCARD_EXTENSION SmartcardExtension; PDEVICE_EXTENSION DeviceExtension; SmartcardDebug(DEBUG_TRACE, ("%s!ReadStateAfterP1Stalled: Enter\n",DRIVER_NAME)); DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(DeviceObject, 0x20, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitReadState; } SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitReadState; } SmartcardDebug(DEBUG_TRACE, ("%s!ReadStateAfterP1Stalled: Exit %lx\n",DRIVER_NAME,NTStatus)); ExitReadState: return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_PowerOnCard ( IN PSMARTCARD_EXTENSION SmartcardExtension, IN PUCHAR pbATR, OUT PULONG pulATRLength ) { UCHAR abMaxAtrBuffer[SCARD_ATR_LENGTH]; ULONG ulCurrentLengthOfAtr; ULONG ulPtrToCurrentAtrByte; ULONG ulExpectedLengthOfAtr; BOOLEAN fTryNextCard; BOOLEAN fValidAtrReceived = FALSE; ULONG ulBytesRead; NTSTATUS NTStatus; PDEVICE_OBJECT DeviceObject; NTSTATUS DebugStatus; BOOLEAN fInverseAtr = FALSE; ULONG ulHistoricalBytes; ULONG i; BOOLEAN fTDxSent; BOOLEAN fOnlyT0; UCHAR bResetMode; UCHAR abFrequency[2] = {CMUSB_FREQUENCY_3_72MHZ, CMUSB_FREQUENCY_5_12MHZ}; ULONG ulCardType; UCHAR bCardType; UCHAR bStopBits; UCHAR bBaudRate; SmartcardDebug(DEBUG_TRACE, ("%s!PowerOnCard: Enter\n",DRIVER_NAME)); DeviceObject = SmartcardExtension->OsData->DeviceObject; if (SmartcardExtension->MinorIoControlCode == SCARD_COLD_RESET) bResetMode = SMARTCARD_COLD_RESET; else bResetMode = SMARTCARD_WARM_RESET; // clear card parameters SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = 0; SmartcardExtension->ReaderExtension->CardParameters.bCardType = 0; SmartcardExtension->ReaderExtension->CardParameters.bStopBits = 0; // set default card parameters // asnyc, 9600 baud, even parity bStopBits = 2; bBaudRate = CMUSB_BAUDRATE_9600; bCardType = CMUSB_SMARTCARD_ASYNCHRONOUS; for (ulCardType = 0;ulCardType < 2;ulCardType++) { #if DBG switch (ulCardType) { case 0: SmartcardDebug(DEBUG_ATR, ("%s!PowerOnCard: trying 3.72 Mhz smart card\n",DRIVER_NAME)); break; case 1: SmartcardDebug(DEBUG_ATR, ("%s!PowerOnCard: trying 5.12 Mhz smart card\n",DRIVER_NAME)); break; } #endif bBaudRate |= abFrequency[ulCardType]; NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, bCardType, bBaudRate, bStopBits); if (NTStatus != STATUS_SUCCESS) { // if we can't set the card parameters there must be a serious error goto ExitPowerOnCard; } ulCurrentLengthOfAtr = 0L; ulPtrToCurrentAtrByte = 0L; fOnlyT0 = TRUE; fTryNextCard = FALSE; fValidAtrReceived = FALSE; RtlFillMemory((PVOID)abMaxAtrBuffer, sizeof(abMaxAtrBuffer), 0x00); // resync CardManUSB by reading the NTStatus byte SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(DeviceObject, 0x20, //bRequest, 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitPowerOnCard; } SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; SmartcardExtension->SmartcardReply.BufferLength = 1; NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOnCard; } else if (NTStatus != STATUS_SUCCESS) { // if we can't read the NTStatus there must be a serious error goto ExitPowerOnCard; } // check if card is really inserted if (SmartcardExtension->SmartcardReply.Buffer[0] == 0x00) { NTStatus = STATUS_NO_MEDIA; goto ExitPowerOnCard; } // issue power on command NTStatus = CMUSB_WriteP0(DeviceObject, 0x10, //bRequest, bResetMode, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00 //bIndexHi, ); if (NTStatus != STATUS_SUCCESS) { // if we can't issue the power on command there must be a serious error goto ExitPowerOnCard; } SmartcardExtension->ReaderExtension->ulTimeoutP1 = DEFAULT_TIMEOUT_P1; NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOnCard; } else if (NTStatus != STATUS_SUCCESS) { continue; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(abMaxAtrBuffer+ulCurrentLengthOfAtr), (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); // check if inverse convention used if (abMaxAtrBuffer[0] == 0x03) { fInverseAtr = TRUE; } if (fInverseAtr) { CMUSB_InverseBuffer(abMaxAtrBuffer+ulCurrentLengthOfAtr, ulBytesRead); } if (abMaxAtrBuffer[0] != 0x3B && abMaxAtrBuffer[0] != 0x3F ) { continue; // try next card } ulCurrentLengthOfAtr += ulBytesRead; // --------------------- // TS character // --------------------- SmartcardDebug(DEBUG_ATR,("PowerOnCard: TS = %2.2x\n",abMaxAtrBuffer[0])); if (abMaxAtrBuffer[ulPtrToCurrentAtrByte] != 0x3B && abMaxAtrBuffer[ulPtrToCurrentAtrByte] != 0x3F ) { continue; } // --------------------- // T0 character // --------------------- ulExpectedLengthOfAtr = 2; if (ulCurrentLengthOfAtr < ulExpectedLengthOfAtr) { NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOnCard; } else if (NTStatus != STATUS_SUCCESS) { continue; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(abMaxAtrBuffer+ulCurrentLengthOfAtr), (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); if (fInverseAtr) { CMUSB_InverseBuffer(abMaxAtrBuffer+ulCurrentLengthOfAtr, ulBytesRead); } ulCurrentLengthOfAtr += ulBytesRead; } SmartcardDebug(DEBUG_ATR,("PowerOnCard: T0 = %2.2x\n",abMaxAtrBuffer[1])); ulHistoricalBytes = abMaxAtrBuffer[1] & 0x0F; do { ulPtrToCurrentAtrByte = ulExpectedLengthOfAtr - 1; fTDxSent = FALSE; if (abMaxAtrBuffer[ulPtrToCurrentAtrByte] & 0x10) ulExpectedLengthOfAtr++; if (abMaxAtrBuffer[ulPtrToCurrentAtrByte] & 0x20) ulExpectedLengthOfAtr++; if (abMaxAtrBuffer[ulPtrToCurrentAtrByte] & 0x40) ulExpectedLengthOfAtr++; if (abMaxAtrBuffer[ulPtrToCurrentAtrByte] & 0x80) { ulExpectedLengthOfAtr++; fTDxSent = TRUE; } if (fOnlyT0 == TRUE && ulPtrToCurrentAtrByte != 1 && // check if not T0 (abMaxAtrBuffer[ulPtrToCurrentAtrByte ] & 0x0f) ) { fOnlyT0 = FALSE; } // TA1, TB1, TC1 , TD1 while (ulCurrentLengthOfAtr < ulExpectedLengthOfAtr) { NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOnCard; } else if (NTStatus != STATUS_SUCCESS) { fTryNextCard = TRUE; break; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(abMaxAtrBuffer+ulCurrentLengthOfAtr), (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); if (fInverseAtr) { CMUSB_InverseBuffer(abMaxAtrBuffer+ulCurrentLengthOfAtr, ulBytesRead); } ulCurrentLengthOfAtr += ulBytesRead; } // end of while if (fTryNextCard == TRUE) { break; } #ifdef DBG SmartcardDebug(DEBUG_ATR,("PowerOnCard: ATR read bytes: ")); for (i = 0;i < ulExpectedLengthOfAtr;i++) SmartcardDebug(DEBUG_ATR,("%2.2x ",abMaxAtrBuffer[i])); SmartcardDebug(DEBUG_ATR,("\n")); #endif } while (fTDxSent == TRUE); if (fTryNextCard == TRUE) { continue; } // read historical bytes // bug fix : old SAMOS cards have a damaged ATR if (abMaxAtrBuffer[0] == 0x3b && abMaxAtrBuffer[1] == 0xbf && abMaxAtrBuffer[2] == 0x11 && abMaxAtrBuffer[3] == 0x00 && abMaxAtrBuffer[4] == 0x81 && abMaxAtrBuffer[5] == 0x31 && abMaxAtrBuffer[6] == 0x90 && abMaxAtrBuffer[7] == 0x73 ) { ulHistoricalBytes = 4; } ulExpectedLengthOfAtr += ulHistoricalBytes; if (fOnlyT0 == FALSE) { ulExpectedLengthOfAtr ++; } while (ulCurrentLengthOfAtr < ulExpectedLengthOfAtr) { NTStatus = CMUSB_ReadP1(DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); goto ExitPowerOnCard; } else if (NTStatus != STATUS_SUCCESS) { fTryNextCard = TRUE; break; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)(abMaxAtrBuffer+ulCurrentLengthOfAtr), (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); if (fInverseAtr) { CMUSB_InverseBuffer(abMaxAtrBuffer+ulCurrentLengthOfAtr, ulBytesRead); } ulCurrentLengthOfAtr += ulBytesRead; } if (fTryNextCard == TRUE) { continue; } // check ATR if (ulCurrentLengthOfAtr < 3 || ulCurrentLengthOfAtr > SCARD_ATR_LENGTH ) { goto ExitPowerOnCard; } // check if the ATR of a SAMOS card with damaged ATR msut be corrected CMUSB_CheckAtrModified(abMaxAtrBuffer,ulCurrentLengthOfAtr); NTStatus = STATUS_SUCCESS; fValidAtrReceived = TRUE; RtlCopyBytes((PVOID)pbATR, (PVOID)abMaxAtrBuffer, ulCurrentLengthOfAtr); *pulATRLength = ulCurrentLengthOfAtr; if (fInverseAtr) { SmartcardExtension->ReaderExtension->fInverseAtr = TRUE; } else { SmartcardExtension->ReaderExtension->fInverseAtr = FALSE; } SmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE; // ------------------- // set card parameters // ------------------- if (SmartcardExtension->ReaderExtension->fInverseAtr) { SmartcardExtension->ReaderExtension->CardParameters.bBaudRate |= CMUSB_ODD_PARITY; } SmartcardExtension->ReaderExtension->CardParameters.bBaudRate |= abFrequency[ulCardType]; SmartcardExtension->ReaderExtension->CardParameters.bBaudRate |= CMUSB_BAUDRATE_9600; SmartcardExtension->ReaderExtension->CardParameters.bCardType = CMUSB_SMARTCARD_ASYNCHRONOUS; break; } ExitPowerOnCard: // return correct error code if (NTStatus != STATUS_NO_MEDIA && fValidAtrReceived == FALSE) { SmartcardDebug(DEBUG_ATR, ("%s!PowerOnCard: no valid ATR received\n",DRIVER_NAME)); NTStatus = STATUS_UNRECOGNIZED_MEDIA; } if (NTStatus!=STATUS_SUCCESS) { // turn off VCC again CMUSB_PowerOffCard (SmartcardExtension ); // ignor NTStatus } SmartcardDebug(DEBUG_TRACE, ("%s!PowerOnCard: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_CardTracking( PSMARTCARD_EXTENSION pSmartcardExtension ) { KIRQL oldIrql; SmartcardDebug(DEBUG_TRACE, ("%s!CardTracking: Enter\n",DRIVER_NAME )); // // Set cancel routine for the notification irp // IoAcquireCancelSpinLock(&oldIrql); IoSetCancelRoutine(pSmartcardExtension->OsData->NotificationIrp, CMUSB_CancelCardTracking); IoReleaseCancelSpinLock(oldIrql); // // Mark notification irp pending // IoMarkIrpPending(pSmartcardExtension->OsData->NotificationIrp); SmartcardDebug(DEBUG_TRACE, ("%s!CardTracking: Exit\n",DRIVER_NAME )); return STATUS_PENDING; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_Cleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension; SmartcardDebug(DEBUG_TRACE, ("%s!Cleanup: Enter\n",DRIVER_NAME)); if (SmartcardExtension->OsData->NotificationIrp != NULL && // test if there is a pending IRP at all SmartcardExtension->ReaderExtension != NULL && // if the device has been removed ReaderExtension == NULL DeviceExtension->lOpenCount == 1 ) // complete card tracking only if this is the the last close call // otherwise the card tracking of the resource manager is canceled { // // We need to complete the notification irp // CMUSB_CompleteCardTracking(SmartcardExtension); } SmartcardDebug(DEBUG_DRIVER, ("%s!Cleanup: Completing IRP %lx\n",DRIVER_NAME,Irp)); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp,IO_NO_INCREMENT); SmartcardDebug(DEBUG_TRACE, ("%s!Cleanup: Exit\n",DRIVER_NAME)); return STATUS_SUCCESS; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_CancelCardTracking( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension; SmartcardDebug(DEBUG_TRACE, ("%s!CancelCardTracking: Enter\n",DRIVER_NAME)); ASSERT(Irp == SmartcardExtension->OsData->NotificationIrp); IoReleaseCancelSpinLock(Irp->CancelIrql); CMUSB_CompleteCardTracking(SmartcardExtension); SmartcardDebug(DEBUG_TRACE, ("%s!CancelCardTracking: Exit\n",DRIVER_NAME)); return STATUS_CANCELLED; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_IoCtlVendor( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; NTSTATUS DebugStatus; UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength; SmartcardDebug(DEBUG_TRACE, ("%s!IoCtlVendor : Enter\n",DRIVER_NAME)); switch (SmartcardExtension->MajorIoControlCode) { case CM_IOCTL_CR80S_SAMOS_SET_HIGH_SPEED: NTStatus = CMUSB_SetHighSpeed_CR80S_SAMOS(SmartcardExtension); break; case CM_IOCTL_GET_FW_VERSION: NTStatus = CMUSB_GetFWVersion(SmartcardExtension); break; case CM_IOCTL_READ_DEVICE_DESCRIPTION: NTStatus = CMUSB_ReadDeviceDescription(SmartcardExtension); break; case CM_IOCTL_SET_READER_9600_BAUD: NTStatus = CMUSB_SetReader_9600Baud(SmartcardExtension); break; case CM_IOCTL_SET_READER_38400_BAUD: NTStatus = CMUSB_SetReader_38400Baud(SmartcardExtension); break; case CM_IOCTL_SET_SYNC_PARAMETERS: // in case of CardManUSB do nothing NTStatus = STATUS_SUCCESS; break; case CM_IOCTL_SYNC_CARD_POWERON: NTStatus = CMUSB_PowerOnSynchronousCard(SmartcardExtension, pbAtrBuffer, &ulAtrLength); break; case CM_IOCTL_2WBP_RESET_CARD: SmartcardExtension->MinorIoControlCode = SMARTCARD_WARM_RESET; NTStatus = CMUSB_PowerOnSynchronousCard(SmartcardExtension, pbAtrBuffer, &ulAtrLength); break; case CM_IOCTL_2WBP_TRANSFER: NTStatus = CMUSB_Transmit2WBP(SmartcardExtension); break; case CM_IOCTL_3WBP_TRANSFER: NTStatus = CMUSB_Transmit3WBP(SmartcardExtension); break; default: NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; } SmartcardDebug(DEBUG_TRACE, ("%s!IoCtlVendor : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS *****************************************************************************/ NTSTATUS CMUSB_SetHighSpeed_CR80S_SAMOS ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; NTSTATUS DebugStatus; UCHAR abReadBuffer[16]; ULONG ulBytesRead; BYTE abCR80S_SAMOS_SET_HIGH_SPEED[4] = {0xFF,0x11,0x94,0x7A}; ULONG ulAtrLength; BYTE abAtr[MAXIMUM_ATR_LENGTH]; LARGE_INTEGER liWaitTime; BOOLEAN fStateTimer; ULONG ulWaitTime; BOOLEAN fCancelTimer = FALSE; SmartcardDebug(DEBUG_TRACE, ("%s!SetHighSpeed_CR80S_SAMOS: Enter\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetHighSpeed_CR80S_SAMOS: writing high speed command\n",DRIVER_NAME)); RtlCopyBytes((PVOID)SmartcardExtension->SmartcardRequest.Buffer, (PVOID)abCR80S_SAMOS_SET_HIGH_SPEED, sizeof(abCR80S_SAMOS_SET_HIGH_SPEED)); SmartcardExtension->SmartcardRequest.BufferLength = 4; NTStatus = CMUSB_WriteP0(SmartcardExtension->OsData->DeviceObject, 0x01, //we can use T=1 setting for direct communication 0x00, //bValueLo, 0x00, //bValueHi, 0x00, //bIndexLo, 0x00); //bIndexHi, if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR, ("%s!SetHighSpeed_CR80S_SAMOS: writing high speed command failed\n",DRIVER_NAME)); goto ExitSetHighSpeed; } // read back pts data SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetHighSpeed_CR80S_SAMOS: reading echo\n",DRIVER_NAME)); // maximim initial waiting time is 9600 * etu // => 1 sec is sufficient ulWaitTime = 1000; liWaitTime = RtlConvertLongToLargeInteger(ulWaitTime * -10000); KeSetTimer(&SmartcardExtension->ReaderExtension->WaitTimer, liWaitTime, NULL); fCancelTimer = TRUE; do { SmartcardExtension->ReaderExtension->ulTimeoutP1 = ulWaitTime; NTStatus = CMUSB_ReadP1(SmartcardExtension->OsData->DeviceObject); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { DebugStatus = CMUSB_ReadStateAfterP1Stalled(SmartcardExtension->OsData->DeviceObject); break; } fStateTimer = KeReadStateTimer(&SmartcardExtension->ReaderExtension->WaitTimer); if (fStateTimer == TRUE) { fCancelTimer =FALSE; SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetHighSpeed_CR80S_SAMOS: timeout while reading echo\n",DRIVER_NAME)); break; } } while (SmartcardExtension->SmartcardReply.Buffer[0] < 4 ); if (NTStatus != STATUS_SUCCESS) { goto ExitSetHighSpeed; } SmartcardExtension->SmartcardReply.BufferLength = 4; NTStatus = CMUSB_ReadP0(SmartcardExtension->OsData->DeviceObject); if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR, ("%s!SetHighSpeed_CR80S_SAMOS: reading echo failed\n",DRIVER_NAME)); goto ExitSetHighSpeed; } ulBytesRead = SmartcardExtension->SmartcardReply.BufferLength; RtlCopyBytes((PVOID)abReadBuffer, (PVOID)SmartcardExtension->SmartcardReply.Buffer, ulBytesRead); // if the card has accepted this string , the string is echoed if (abReadBuffer[0] == abCR80S_SAMOS_SET_HIGH_SPEED[0] && abReadBuffer[1] == abCR80S_SAMOS_SET_HIGH_SPEED[1] && abReadBuffer[2] == abCR80S_SAMOS_SET_HIGH_SPEED[2] && abReadBuffer[3] == abCR80S_SAMOS_SET_HIGH_SPEED[3] ) { SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = 0; SmartcardExtension->ReaderExtension->CardParameters.bBaudRate |= CMUSB_FREQUENCY_5_12MHZ; SmartcardExtension->ReaderExtension->CardParameters.bBaudRate |= CMUSB_BAUDRATE_76800; SmartcardExtension->ReaderExtension->CardParameters.bCardType = CMUSB_SMARTCARD_ASYNCHRONOUS; NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, SmartcardExtension->ReaderExtension->CardParameters.bCardType, SmartcardExtension->ReaderExtension->CardParameters.bBaudRate, SmartcardExtension->ReaderExtension->CardParameters.bStopBits); } else { DebugStatus = CMUSB_PowerOffCard(SmartcardExtension); // a cold reset is necessary now SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; DebugStatus = CMUSB_PowerOnCard(SmartcardExtension,abAtr,&ulAtrLength); NTStatus = STATUS_UNSUCCESSFUL; } ExitSetHighSpeed: if (fCancelTimer == TRUE) { KeCancelTimer(&SmartcardExtension->ReaderExtension->WaitTimer); } *SmartcardExtension->IoRequest.Information = 0L; if (NTStatus != STATUS_SUCCESS) NTStatus = STATUS_UNSUCCESSFUL; SmartcardDebug(DEBUG_TRACE, ("%s!SetHighSpeed_CR80S_SAMOS: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_GetFWVersion ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; SmartcardDebug(DEBUG_TRACE, ("%s!GetFWVersion : Enter\n",DRIVER_NAME)); if (SmartcardExtension->IoRequest.ReplyBufferLength < sizeof (ULONG)) { NTStatus = STATUS_BUFFER_OVERFLOW; goto ExitGetFWVersion; } else { *(PULONG)(SmartcardExtension->IoRequest.ReplyBuffer) = SmartcardExtension->ReaderExtension->ulFWVersion; } ExitGetFWVersion: *SmartcardExtension->IoRequest.Information = sizeof(ULONG); SmartcardDebug(DEBUG_TRACE, ("%s!GetFWVersion : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS *****************************************************************************/ NTSTATUS CMUSB_SetReader_9600Baud ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; KIRQL irql; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_9600Baud: Enter\n",DRIVER_NAME)); // check if card is already in specific mode KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) { KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetReader9600; } else { KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); } // set 9600 Baud for 3.58 MHz SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_9600; SmartcardExtension->ReaderExtension->CardParameters.bCardType = CMUSB_SMARTCARD_ASYNCHRONOUS; NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, SmartcardExtension->ReaderExtension->CardParameters.bCardType, SmartcardExtension->ReaderExtension->CardParameters.bBaudRate, SmartcardExtension->ReaderExtension->CardParameters.bStopBits); ExitSetReader9600: *SmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_9600Baud: Exit %lx\n",DRIVER_NAME,NTStatus)); return(NTStatus); } /***************************************************************************** Routine Description: Arguments: Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS *****************************************************************************/ NTSTATUS CMUSB_SetReader_38400Baud ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; KIRQL irql; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_38400Baud: Enter\n",DRIVER_NAME)); // check if card is already in specific mode KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql); if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) { KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetReader38400; } else { KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql); } // set 384000 Baud for 3.58 MHz card SmartcardExtension->ReaderExtension->CardParameters.bBaudRate = CMUSB_FREQUENCY_3_72MHZ + CMUSB_BAUDRATE_38400; SmartcardExtension->ReaderExtension->CardParameters.bCardType = CMUSB_SMARTCARD_ASYNCHRONOUS; NTStatus = CMUSB_SetCardParameters (SmartcardExtension->OsData->DeviceObject, SmartcardExtension->ReaderExtension->CardParameters.bCardType, SmartcardExtension->ReaderExtension->CardParameters.bBaudRate, SmartcardExtension->ReaderExtension->CardParameters.bStopBits); ExitSetReader38400: *SmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_38400Baud: Exit %lx\n",DRIVER_NAME,NTStatus)); return(NTStatus); } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID CMUSB_InitializeSmartcardExtension( IN PSMARTCARD_EXTENSION SmartcardExtension ) { // ================================== // Fill the Vendor_Attr structure // ================================== RtlCopyBytes((PVOID)SmartcardExtension->VendorAttr.VendorName.Buffer, (PVOID)CM2020_VENDOR_NAME, sizeof(CM2020_VENDOR_NAME) ); // // Length of vendor name // SmartcardExtension->VendorAttr.VendorName.Length = sizeof(CM2020_VENDOR_NAME); // // Reader name // RtlCopyBytes((PVOID)SmartcardExtension->VendorAttr.IfdType.Buffer, (PVOID)CM2020_PRODUCT_NAME, sizeof(CM2020_PRODUCT_NAME)); // // Length of reader name // SmartcardExtension->VendorAttr.IfdType.Length = sizeof(CM2020_PRODUCT_NAME); // // Version number // SmartcardExtension->VendorAttr.IfdVersion.BuildNumber = BUILDNUMBER_CARDMAN_USB; SmartcardExtension->VendorAttr.IfdVersion.VersionMinor = VERSIONMINOR_CARDMAN_USB; SmartcardExtension->VendorAttr.IfdVersion.VersionMajor = VERSIONMAJOR_CARDMAN_USB; // // Unit number which is zero based // SmartcardExtension->VendorAttr.UnitNo = SmartcardExtension->ReaderExtension->ulDeviceInstance; // ================================================ // Fill the SCARD_READER_CAPABILITIES structure // =============================================== // // Supported protoclols by the reader // SmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0; // // Reader type serial, keyboard, .... // SmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_USB; // // Mechanical characteristics like swallows etc. // SmartcardExtension->ReaderCapabilities.MechProperties = 0; // // Current state of the reader // SmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN; SmartcardExtension->ReaderExtension->ulNewCardState = UNKNOWN; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN; // // Data Rate // SmartcardExtension->ReaderCapabilities.DataRate.Default = SmartcardExtension->ReaderCapabilities.DataRate.Max = dataRatesSupported[0]; // reader could support higher data rates SmartcardExtension->ReaderCapabilities.DataRatesSupported.List = dataRatesSupported; SmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]); // // CLK Frequency // SmartcardExtension->ReaderCapabilities.CLKFrequency.Default = SmartcardExtension->ReaderCapabilities.CLKFrequency.Max = CLKFrequenciesSupported[0]; // reader could support higher frequencies SmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.List = CLKFrequenciesSupported; SmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.Entries = sizeof(CLKFrequenciesSupported) / sizeof(CLKFrequenciesSupported[0]); // // MaxIFSD // SmartcardExtension->ReaderCapabilities.MaxIFSD = ATTR_MAX_IFSD_CARDMAN_USB; } /***************************************************************************** Routine Description: This function always returns 'CardManUSB'. Arguments: pointer to SMARTCARD_EXTENSION Return Value: NT NTStatus *****************************************************************************/ NTSTATUS CMUSB_ReadDeviceDescription(IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; BYTE abDeviceDescription[] = "CardManUSB"; SmartcardDebug(DEBUG_TRACE, ("%s!ReadDeviceDescription : Enter\n",DRIVER_NAME)); if (SmartcardExtension->IoRequest.ReplyBufferLength < sizeof(abDeviceDescription)) { NTStatus = STATUS_BUFFER_OVERFLOW; *SmartcardExtension->IoRequest.Information = 0L; goto ExitReadDeviceDescription; } else { RtlCopyBytes((PVOID)SmartcardExtension->IoRequest.ReplyBuffer, (PVOID)abDeviceDescription, sizeof(abDeviceDescription)); *SmartcardExtension->IoRequest.Information = sizeof(abDeviceDescription); } ExitReadDeviceDescription: SmartcardDebug(DEBUG_TRACE, ("%s!ReadDeviceDescription : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: This routine always returns FALSE. Arguments: pointer to SMARDCARD_EXTENSION Return Value: NT NTStatus *****************************************************************************/ NTSTATUS CMUSB_IsSPESupported (IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; SmartcardDebug(DEBUG_TRACE, ("%s!IsSPESupported: Enter\n",DRIVER_NAME)); if (SmartcardExtension->IoRequest.ReplyBufferLength < sizeof (ULONG)) { NTStatus = STATUS_BUFFER_OVERFLOW; *SmartcardExtension->IoRequest.Information = 0; goto ExitIsSPESupported; } else { *(PULONG)(SmartcardExtension->IoRequest.ReplyBuffer) = FALSE; *SmartcardExtension->IoRequest.Information = sizeof(ULONG); } ExitIsSPESupported: SmartcardDebug(DEBUG_TRACE, ("%s!IsSPESupported: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS CMUSB_SetCardParameters ( IN PDEVICE_OBJECT DeviceObject, IN UCHAR bCardType, IN UCHAR bBaudRate, IN UCHAR bStopBits ) { NTSTATUS NTStatus; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; SmartcardDebug(DEBUG_TRACE, ("%s!SetCardParameters: Enter\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetCardParameters: ##################################################\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetCardParameters: bCardType = %x bBaudRate = %x bStopBits = %x\n",DRIVER_NAME, bCardType,bBaudRate,bStopBits)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetCardParameters: ##################################################\n",DRIVER_NAME)); DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension; SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = CMUSB_WriteP0(DeviceObject, 0x30, //bRequest, bCardType, //bValueLo, bBaudRate, //bValueHi, bStopBits, //bIndexLo, 0x00 //bIndexHi, ); SmartcardDebug(DEBUG_TRACE, ("%s!SetCardParameters: Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; } /***************************************************************************** Routine Description: Bit0 -> Bit 7 Bit1 -> Bit 6 Bit2 -> Bit 5 Bit3 -> Bit 4 Bit4 -> Bit 3 Bit5 -> Bit 2 Bit6 -> Bit 1 Bit7 -> Bit 0 Arguments: Return Value: *****************************************************************************/ VOID CMUSB_InverseBuffer ( PUCHAR pbBuffer, ULONG ulBufferSize ) { ULONG i; ULONG j; ULONG m; ULONG n; for (i=0; i> (9-j)); } pbBuffer[i] = (UCHAR)~n; } return; } /***************************************************************************** Routine Description: This function checks if an incorrect ATR has been received. It corrects the number of historical bytes and the checksum byte Arguments: pointer to current ATR length of ATR Return Value: none *****************************************************************************/ VOID CMUSB_CheckAtrModified ( PUCHAR pbBuffer, ULONG ulBufferSize ) { UCHAR bNumberHistoricalBytes; UCHAR bXorChecksum; ULONG i; if (ulBufferSize < 0x09) // mininmum length of a modified ATR return ; // ATR is ok // variant 2 if (pbBuffer[0] == 0x3b && pbBuffer[1] == 0xbf && pbBuffer[2] == 0x11 && pbBuffer[3] == 0x00 && pbBuffer[4] == 0x81 && pbBuffer[5] == 0x31 && pbBuffer[6] == 0x90 && pbBuffer[7] == 0x73 && ulBufferSize == 13 ) { // correct number of historical bytes bNumberHistoricalBytes = 4; pbBuffer[1] &= 0xf0; pbBuffer[1] |= bNumberHistoricalBytes; // correct checksum byte bXorChecksum = pbBuffer[1]; for (i=2;i