/***************************************************************************** @doc INT EXT ****************************************************************************** * $ProjectName: $ * $ProjectRevision: $ *----------------------------------------------------------------------------- * $Source: z:/pr/cmbs0/sw/sccmn50m.ms/rcs/sccmcb.c $ * $Revision: 1.7 $ *----------------------------------------------------------------------------- * $Author: WFrischauf $ *----------------------------------------------------------------------------- * History: see EOF *----------------------------------------------------------------------------- * * Copyright © 2000 OMNIKEY AG ******************************************************************************/ #include #include "sccmn50m.h" static ULONG dataRatesSupported[] = {9600,38400}; static ULONG CLKFrequenciesSupported[] = {4000,5000}; /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_CardPower(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS DebugStatus = STATUS_SUCCESS; UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH]; UCHAR abSyncAtrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength; #if DBG ULONG i; #endif; SmartcardDebug( DEBUG_TRACE, ( "%s!CardPower: Enter\n", DRIVER_NAME) ); #if DBG switch (pSmartcardExtension->MinorIoControlCode) { case SCARD_WARM_RESET: SmartcardDebug( DEBUG_ATR, ( "%s!SCARD_WARM_RESTART\n", DRIVER_NAME) ); break; case SCARD_COLD_RESET: SmartcardDebug( DEBUG_ATR, ( "%s!SCARD_COLD_RESTART\n", DRIVER_NAME) ); break; case SCARD_POWER_DOWN: SmartcardDebug( DEBUG_ATR, ( "%s!SCARD_POWER_DOWN\n", DRIVER_NAME) ); break; } #endif //DbgBreakPoint(); switch (pSmartcardExtension->MinorIoControlCode) { case SCARD_WARM_RESET: case SCARD_COLD_RESET: status = SCCMN50M_PowerOn(pSmartcardExtension, &ulAtrLength, pbAtrBuffer, sizeof(pbAtrBuffer)); if (status != STATUS_SUCCESS) { goto ExitReaderPower; } pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength; if (pSmartcardExtension->ReaderExtension->fRawModeNecessary == FALSE) { // copy ATR to smart card structure // the lib needs the ATR for evaluation of the card parameters MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer, sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer), pbAtrBuffer, ulAtrLength); pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength; pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; status = SmartcardUpdateCardCapabilities(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitReaderPower; } // add extra guard time value to card stop bits pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = (UCHAR)(pSmartcardExtension->CardCapabilities.N); // copy ATR to user space MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer, pSmartcardExtension->IoRequest.ReplyBufferLength, pbAtrBuffer, ulAtrLength); *pSmartcardExtension->IoRequest.Information = ulAtrLength; #if DBG SmartcardDebug(DEBUG_ATR, ("%s!ATR : ", DRIVER_NAME)); for (i = 0;i < ulAtrLength;i++) { SmartcardDebug(DEBUG_ATR, ("%2.2x ", pSmartcardExtension->CardCapabilities.ATR.Buffer[i])); } SmartcardDebug(DEBUG_ATR,("\n")); #endif } else { abSyncAtrBuffer[0] = 0x3B; abSyncAtrBuffer[1] = 0x04; MemCpy(&abSyncAtrBuffer[2], sizeof(abSyncAtrBuffer)-2, pbAtrBuffer, ulAtrLength); ulAtrLength += 2; MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer, sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer), abSyncAtrBuffer, ulAtrLength); pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)(ulAtrLength); pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; status = SmartcardUpdateCardCapabilities(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitReaderPower; } SmartcardDebug(DEBUG_ATR,("ATR of synchronous smart card : %2.2x %2.2x %2.2x %2.2x\n", pbAtrBuffer[0],pbAtrBuffer[1],pbAtrBuffer[2],pbAtrBuffer[3])); pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE; // copy ATR to user space MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer, pSmartcardExtension->IoRequest.ReplyBufferLength, abSyncAtrBuffer, ulAtrLength); *pSmartcardExtension->IoRequest.Information = ulAtrLength; } break; case SCARD_POWER_DOWN: status = SCCMN50M_PowerOff(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitReaderPower; } pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; break; } ExitReaderPower: SmartcardDebug( DEBUG_TRACE, ( "%s!CardPower: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_PowerOn ( IN PSMARTCARD_EXTENSION pSmartcardExtension, OUT PULONG pulAtrLength, OUT PUCHAR pbAtrBuffer, IN ULONG ulAtrBufferSize ) { NTSTATUS status; NTSTATUS DebugStatus; // We always use 0x80 for reset delay pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0x80; if (SCCMN50M_IsAsynchronousSmartCard(pSmartcardExtension) == TRUE) { if (pSmartcardExtension->MinorIoControlCode == SCARD_COLD_RESET) { status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize, FALSE); // if cold reset was not succesfull ,it maybe a SAMOS card with the sensor bug if (status != STATUS_SUCCESS) { status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize, TRUE); if (status != STATUS_SUCCESS) { status = SCCMN50M_UseParsingStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize); } } } else { status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize, TRUE); if (status != STATUS_SUCCESS) { status = SCCMN50M_UseParsingStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize); } } } else { SmartcardDebug(DEBUG_ATR, ("check if synchronous smart card is inserted\n")); // try to find a synchronous smart card status = SCCMN50M_UseSyncStrategy(pSmartcardExtension, pulAtrLength, pbAtrBuffer, ulAtrBufferSize); } if (status != STATUS_SUCCESS) { // smart card not powered status = STATUS_UNRECOGNIZED_MEDIA; *pulAtrLength = 0; DebugStatus = SCCMN50M_PowerOff(pSmartcardExtension); return status; } else { // add extra guard time value to card stop bits pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = (UCHAR)(pSmartcardExtension->CardCapabilities.N); return status; } } /***************************************************************************** Routine Description: This routine inverts the buffer 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: pbBuffer ... pointer to buffer ulBufferSize ... size of buffer Return Value: none *****************************************************************************/ VOID SCCMN50M_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 always permforms a cold reset of the smart card. A SAMOS card with the sensor bug will not be powered by this function. Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_UseParsingStrategy (IN PSMARTCARD_EXTENSION pSmartcardExtension, OUT PULONG pulAtrLength, OUT PUCHAR pbAtrBuffer, IN ULONG ulAtrBufferSize ) { NTSTATUS status; NTSTATUS DebugStatus; UCHAR ulCardType; UCHAR ReadBuffer[SCARD_ATR_LENGTH]; UCHAR bAtrBytesRead[SCARD_ATR_LENGTH]; ULONG ulBytesRead; BOOLEAN fInverseAtr = FALSE; ULONG ulAtrBufferOffset = 0; ULONG ulHistoricalBytes; ULONG ulNextStepBytesToRead; ULONG ulPrevStepBytesRead; ULONG i; BOOLEAN fTDxSent; BOOLEAN fAtrParsed; BOOLEAN fOnlyT0 = TRUE; ULONG ulOldReadTotalTimeoutMultiplier; // DBGBreakPoint(); // set ReadTotalTimeoutMultiplier to 250ms (9600 * 372/f = initial waiting time) ulOldReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 250; pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02; for (ulCardType = ASYNC3_CARD;ulCardType <= ASYNC5_CARD;ulCardType++) { // power off + resync status = SCCMN50M_PowerOff(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitUseParsingStrategy; } SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS); SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY); if (ulCardType == ASYNC3_CARD) SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); else SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ); SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, 0, 0, 2); // TS and T0 expected SmartcardDebug(DEBUG_ATR, ("%s!ResetDelay = %d\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay)); // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitUseParsingStrategy; } // read state and length + TS + T0 status = SCCMN50M_ReadCardMan(pSmartcardExtension,4,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); if (status != STATUS_SUCCESS) { continue; // try next card } // contents of read buffer // [0] ... state // [1] ... length // [2] ... TS // [3] ... T0 // TS if (ReadBuffer[2] == CHAR_INV) { fInverseAtr = TRUE; } if (fInverseAtr) SCCMN50M_InverseBuffer(&ReadBuffer[3],1); ulHistoricalBytes = ReadBuffer[3] & 0x0F; ulPrevStepBytesRead = 2; // T0 codes following TA1 - TD1 fAtrParsed = TRUE; SmartcardDebug(DEBUG_ATR, ("%s!Step : Bytes to read = 2\n", DRIVER_NAME)); do { ulNextStepBytesToRead = ulPrevStepBytesRead; fTDxSent = FALSE; if (ReadBuffer[ulBytesRead - 1 ] & 0x10) ulNextStepBytesToRead++; if (ReadBuffer[ulBytesRead - 1 ] & 0x20) ulNextStepBytesToRead++; if (ReadBuffer[ulBytesRead - 1 ] & 0x40) ulNextStepBytesToRead++; if (ReadBuffer[ulBytesRead - 1 ] & 0x80) { ulNextStepBytesToRead++; fTDxSent = TRUE; } if (ulPrevStepBytesRead != 2 && ReadBuffer[ulBytesRead -1 ] & 0x0f) { fOnlyT0 = FALSE; } // ----------------------- // POWER OFF // ----------------------- // turn power off and get state status = SCCMN50M_PowerOff(pSmartcardExtension); if (status != STATUS_SUCCESS) { fAtrParsed = FALSE; goto ExitUseParsingStrategy; // try next card } // ----------------------- // POWER ON // ----------------------- // turn on power flag SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY); if (ulCardType == ASYNC3_CARD) SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); else SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ); SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, 0, 0, (UCHAR)ulNextStepBytesToRead); // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { fAtrParsed = FALSE; goto ExitUseParsingStrategy; // try next card } // read state and length + TAx,TBx,TCx,TDx SmartcardDebug(DEBUG_ATR, ("%s!Step : Bytes to read = %ld\n", DRIVER_NAME, ulNextStepBytesToRead)); status = SCCMN50M_ReadCardMan(pSmartcardExtension,2 + ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); if (status != STATUS_SUCCESS) { fAtrParsed = FALSE; break; // try next card } if (fInverseAtr) SCCMN50M_InverseBuffer(&ReadBuffer[2],ulBytesRead-2); MemCpy(bAtrBytesRead,sizeof(bAtrBytesRead),&ReadBuffer[2],ulBytesRead -2); #if DBG SmartcardDebug(DEBUG_ATR, ("%s!read ATR bytes: ", DRIVER_NAME)); for (i = 0;i < ulBytesRead-2;i++) SmartcardDebug(DEBUG_ATR, ("%2.2x ", bAtrBytesRead[i])); SmartcardDebug(DEBUG_ATR,("\n")); #endif ulPrevStepBytesRead = ulBytesRead - 2; } while (fTDxSent == TRUE); // +++++++++++++++++++++++++++++++++++++++ // now we know how long the whole ATR is // +++++++++++++++++++++++++++++++++++++++ // ----------------------- // POWER OFF // ----------------------- // turn power off and get state status = SCCMN50M_PowerOff(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitUseParsingStrategy; } // ----------------------- // POWER ON // ----------------------- // turn on power flag SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY); if (ulCardType == ASYNC3_CARD) SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); else SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ); // bug fix : old SAMOS cards have a damaged ATR if (bAtrBytesRead[0] == 0x3b && bAtrBytesRead[1] == 0xbf && bAtrBytesRead[2] == 0x11 && bAtrBytesRead[3] == 0x00 && bAtrBytesRead[4] == 0x81 && bAtrBytesRead[5] == 0x31 && bAtrBytesRead[6] == 0x90 && bAtrBytesRead[7] == 0x73 ) { ulHistoricalBytes = 4; } ulNextStepBytesToRead = ulPrevStepBytesRead + ulHistoricalBytes; if (fOnlyT0 == FALSE) ulNextStepBytesToRead++; // TCK ! SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, 0, 0, (UCHAR)ulNextStepBytesToRead); // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitUseParsingStrategy; // try next card } // read whole ATR SmartcardDebug(DEBUG_ATR, ("%s!Step : Bytes to read = %ld\n", DRIVER_NAME, ulNextStepBytesToRead)); status = SCCMN50M_ReadCardMan(pSmartcardExtension,2+ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ATR, ("%s!Reading of whole ATR failed\n !", DRIVER_NAME)); continue; // try next card } // check ATR if (ulBytesRead - 2 < MIN_ATR_LEN) { status = STATUS_UNRECOGNIZED_MEDIA; DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2+ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); goto ExitUseParsingStrategy; } if (ulBytesRead -2 > ulAtrBufferSize) { // the ATR is larger then 33 bytes !!! status = STATUS_BUFFER_OVERFLOW; goto ExitUseParsingStrategy; } SCCMN50M_CheckAtrModified(pbAtrBuffer,*pulAtrLength); // pass ATR and ATR length to calling function MemCpy(pbAtrBuffer,ulAtrBufferSize,&ReadBuffer[2],ulBytesRead -2); *pulAtrLength = ulBytesRead -2; if (fInverseAtr) { SCCMN50M_SetCardControlFlags(pSmartcardExtension,INVERSE_DATA); SCCMN50M_InverseBuffer(pbAtrBuffer,*pulAtrLength); pSmartcardExtension->ReaderExtension->fInverseAtr = TRUE; } else { pSmartcardExtension->ReaderExtension->fInverseAtr = FALSE; } pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE; break; } ExitUseParsingStrategy: pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = ulOldReadTotalTimeoutMultiplier ; SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,IGNORE_PARITY); SCCMN50M_ClearCardManHeader(pSmartcardExtension); return status; } /***************************************************************************** Routine Description: This function performs either a cold or a warm reset depending on the fWarmReset parameter . Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_UseColdWarmResetStrategy (IN PSMARTCARD_EXTENSION pSmartcardExtension, OUT PULONG pulAtrLength, OUT PUCHAR pbAtrBuffer, IN ULONG ulAtrBufferSize, IN BOOLEAN fWarmReset ) { NTSTATUS status; NTSTATUS DebugStatus; ULONG ulCardType; UCHAR bReadBuffer[SCARD_ATR_LENGTH]; ULONG ulBytesRead; ULONG ulOldReadTotalTimeoutMultiplier; //DBGBreakPoint(); // set ReadTotalTimeoutMultiplier to 250ms (9600 * 372/f = initial waiting time) ulOldReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 250; if (fWarmReset == FALSE) { SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,COLD_RESET,ATR_LEN_ASYNC); } else { SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,ATR_LEN_ASYNC); } pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02; for (ulCardType = ASYNC3_CARD;ulCardType <= ASYNC5_CARD;ulCardType++) { SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS); SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR); if (ulCardType == ASYNC3_CARD) { SmartcardDebug( DEBUG_ATR, ("%s!ASYNC_3\n", DRIVER_NAME)); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); } else { SmartcardDebug( DEBUG_ATR, ("%s!ASYN_5\n", DRIVER_NAME)); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ); } status = SCCMN50M_ResyncCardManII(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitUseColdWarmResetStrategy; } // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitUseColdWarmResetStrategy; } pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; // read state and length status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (status != STATUS_SUCCESS) { continue; // try next card } if (bReadBuffer[1] < MIN_ATR_LEN) { // read all remaining bytes from the CardMan DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); status = STATUS_UNRECOGNIZED_MEDIA; goto ExitUseColdWarmResetStrategy; } if (bReadBuffer[1] > ulAtrBufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitUseColdWarmResetStrategy; } // read ATR status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],pulAtrLength,pbAtrBuffer,ulAtrBufferSize); if (status != STATUS_SUCCESS) { continue; } switch (pbAtrBuffer[0]) { case CHAR_INV: pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE; SCCMN50M_SetCardControlFlags(pSmartcardExtension,INVERSE_DATA); SCCMN50M_InverseBuffer(pbAtrBuffer,*pulAtrLength); pSmartcardExtension->ReaderExtension->fInverseAtr = TRUE; break; case CHAR_NORM: pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE; pSmartcardExtension->ReaderExtension->fInverseAtr = FALSE; break; default : status = STATUS_UNRECOGNIZED_MEDIA; goto ExitUseColdWarmResetStrategy; break; } // the smart card has been powered SCCMN50M_CheckAtrModified(pbAtrBuffer,*pulAtrLength); MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer, sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer), pbAtrBuffer, *pulAtrLength); pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)*pulAtrLength; status = SmartcardUpdateCardCapabilities(pSmartcardExtension); if (status != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ATR, ("%s!Invalid ATR received\n", DRIVER_NAME)); goto ExitUseColdWarmResetStrategy; } if (SCCMN50M_IsAtrValid(pbAtrBuffer,*pulAtrLength) == FALSE) { SmartcardDebug( DEBUG_ATR, ("%s!Invalid ATR received\n", DRIVER_NAME)); status = STATUS_UNRECOGNIZED_MEDIA; goto ExitUseColdWarmResetStrategy; } break; } // end for ExitUseColdWarmResetStrategy: pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = ulOldReadTotalTimeoutMultiplier ; SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | IGNORE_PARITY); SCCMN50M_ClearCardManHeader(pSmartcardExtension); return status; } /***************************************************************************** Routine Description: This function checks if the received ATR is valid. Arguments: Return Value: *****************************************************************************/ BOOLEAN SCCMN50M_IsAtrValid( PUCHAR pbAtrBuffer, ULONG ulAtrLength ) { BOOLEAN fAtrValid = TRUE; ULONG ulTD1Offset = 0; BOOLEAN fTD1Transmitted = FALSE; BOOLEAN fOnlyT0 = FALSE; BYTE bXor; ULONG ulHistoricalBytes; ULONG ulTx2Characters = 0; ULONG i; //DBGBreakPoint(); SmartcardDebug( DEBUG_TRACE, ( "%s!IsAtrValid : Enter\n", DRIVER_NAME) ); // basic checks if (ulAtrLength < 2 || (pbAtrBuffer[0] != 0x3F && pbAtrBuffer[0] != 0x3B ) || (pbAtrBuffer[1] & 0xF0) == 0x00 ) { return FALSE; } if (pbAtrBuffer[1] & 0x10) ulTD1Offset++; if (pbAtrBuffer[1] & 0x20) ulTD1Offset++; if (pbAtrBuffer[1] & 0x40) ulTD1Offset++; ulHistoricalBytes = pbAtrBuffer[1] & 0x0F; if (pbAtrBuffer[1] & 0x80) // TD1 in ATR ? { fTD1Transmitted = TRUE; if ((pbAtrBuffer[2 + ulTD1Offset] & 0x0F) == 0x00) // T0 indicated ? fOnlyT0 = TRUE; } else { fOnlyT0 = TRUE; } if (fOnlyT0 == FALSE) { bXor = pbAtrBuffer[1]; for (i=2;iReaderExtension->ulOldCardState == POWERED) pSmartcardExtension->ReaderExtension->ulOldCardState = INSERTED; SmartcardDebug( DEBUG_TRACE, ( "%s!PowerOff: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_Transmit(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; NTSTATUS DebugStatus; switch (pSmartcardExtension->CardCapabilities.Protocol.Selected) { case SCARD_PROTOCOL_RAW: status = STATUS_INVALID_DEVICE_REQUEST; break; case SCARD_PROTOCOL_T0: status = SCCMN50M_TransmitT0(pSmartcardExtension); break; case SCARD_PROTOCOL_T1: status = SCCMN50M_TransmitT1(pSmartcardExtension); break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_TransmitT0(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; NTSTATUS DebugStatus; UCHAR bWriteBuffer[MIN_BUFFER_SIZE]; UCHAR bReadBuffer [MIN_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 = FALSE; BOOLEAN fT0TransferFromCard = FALSE; BOOLEAN fSW1SW2Sent = FALSE; ULONG ulReadTotalTimeoutMultiplier; ULONG ulStatBytesRead; BYTE abStatReadBuffer[2]; //SmartcardDebug(DEBUG_TRACE,("TransmitT0 : Enter\n")); // // Let the lib build a T=0 packet // pSmartcardExtension->SmartcardRequest.BufferLength = 0; // no bytes additionally needed status = SmartcardT0Request(pSmartcardExtension); if (status != STATUS_SUCCESS) { // // This lib detected an error in the data to send. // // ------------------------------------------ // ITSEC E2 requirements: clear write buffers // ------------------------------------------ MemSet(bWriteBuffer, sizeof(bWriteBuffer), '\0', sizeof(bWriteBuffer)); MemSet(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferSize, '\0', pSmartcardExtension->SmartcardRequest.BufferSize); return status; } // increase timeout for T0 Transmission ulReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = pSmartcardExtension->CardCapabilities.T0.WT/1000 + 1500; // ################################## // TRANSPARENT MODE // ################################## ulBytesStillToWrite = ulBytesToWrite = T0_HEADER_LEN + pSmartcardExtension->T0.Lc; ulBytesStillToRead = ulBytesToRead = pSmartcardExtension->T0.Le; if (pSmartcardExtension->T0.Lc) fT0TransferToCard = TRUE; if (pSmartcardExtension->T0.Le) fT0TransferFromCard = TRUE; // copy data to the write buffer /* SmartcardDebug(DEBUG_TRACE,("CLA = %x INS = %x P1 = %x P2 = %X L = %x\n", pSmartcardExtension->SmartcardRequest.Buffer[0], pSmartcardExtension->SmartcardRequest.Buffer[1], pSmartcardExtension->SmartcardRequest.Buffer[2], pSmartcardExtension->SmartcardRequest.Buffer[3], pSmartcardExtension->SmartcardRequest.Buffer[4])); */ MemCpy(bWriteBuffer, sizeof(bWriteBuffer), pSmartcardExtension->SmartcardRequest.Buffer, ulBytesToWrite); bINS = bWriteBuffer[1]; if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { SCCMN50M_InverseBuffer(bWriteBuffer,ulBytesToWrite); } status = SCCMN50M_EnterTransparentMode(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitTransparentTransmitT0; } // STEP 1 : write config + header to enter transparent mode SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, // Tx control 0, // Tx length 0, // Rx control 0); // Rx length status = SCCMN50M_WriteCardMan (pSmartcardExtension, 0, NULL); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } pSmartcardExtension->ReaderExtension->fTransparentMode = TRUE; // if the inserted card uses inverse convention , we must now switch the COM port // to odd parity if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = ODD_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitTransparentTransmitT0; } } ulWriteBufferOffset = 0; ulReadBufferOffset = 0; // STEP 2 : write CLA INS P1 P2 Lc ulBytesToWriteThisStep = 5; status = SCCMN50M_WriteCardMan (pSmartcardExtension, ulBytesToWriteThisStep, bWriteBuffer+ulWriteBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; // STEP 2 : read procedure byte do { do { pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,&bProcedureByte,sizeof(bProcedureByte)); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { SCCMN50M_InverseBuffer(&bProcedureByte,ulBytesRead); } //SmartcardDebug(DEBUG_TRACE,("Procedure byte = %x\n",bProcedureByte)); //SmartcardDebug(DEBUG_TRACE,("waiting time = %x\n",pSmartcardExtension->CardCapabilities.T0.WT)); if (bProcedureByte == 0x60) { // ISO 7816-3 : // This byte is sent by the card to reset the work waiting time and to anticipate // a subsequent procedure byte // => we do nothing here } } while (bProcedureByte == 0x60); // check for ACK if ((bProcedureByte & 0xFE) == (bINS & 0xFE) ) { if (fT0TransferToCard) { ulBytesToWriteThisStep = ulBytesStillToWrite; status = SCCMN50M_WriteCardMan (pSmartcardExtension, ulBytesToWriteThisStep, bWriteBuffer+ulWriteBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; } if (fT0TransferFromCard) { ulBytesToReadThisStep = ulBytesStillToRead; pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,ulBytesToReadThisStep,&ulBytesRead,bReadBuffer + ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead); } ulReadBufferOffset += ulBytesRead; ulBytesStillToRead -= ulBytesRead; } } // check for NAK else if ( (~bProcedureByte & 0xFE) == (bINS & 0xFE)) { if (fT0TransferToCard) { ulBytesToWriteThisStep = 1; status = SCCMN50M_WriteCardMan (pSmartcardExtension, ulBytesToWriteThisStep, bWriteBuffer+ulWriteBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } ulWriteBufferOffset += ulBytesToWriteThisStep; ulBytesStillToWrite -= ulBytesToWriteThisStep; } if (fT0TransferFromCard) { ulBytesToReadThisStep = 1; pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,ulBytesToReadThisStep,&ulBytesRead,bReadBuffer + ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead); } ulReadBufferOffset += ulBytesRead; ulBytesStillToRead -= ulBytesRead; } } // check for SW1 else if ( (bProcedureByte > 0x60 && bProcedureByte <= 0x6F) || (bProcedureByte >= 0x90 && bProcedureByte <= 0x9F) ) { pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; bReadBuffer[ulReadBufferOffset] = bProcedureByte; ulReadBufferOffset++; status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,bReadBuffer+ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead); } ulReadBufferOffset += ulBytesRead; fSW1SW2Sent = TRUE; } else { status = STATUS_UNSUCCESSFUL; goto ExitTransparentTransmitT0; } }while (!fSW1SW2Sent); // copy received bytes MemCpy(pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferSize, bReadBuffer, ulReadBufferOffset); pSmartcardExtension->SmartcardReply.BufferLength = ulReadBufferOffset; // let the lib copy the received bytes to the user buffer status = SmartcardT0Reply(pSmartcardExtension); if (NT_ERROR(status)) { goto ExitTransparentTransmitT0; } ExitTransparentTransmitT0: // ------------------------------------------ // ITSEC E2 requirements: clear write buffers // ------------------------------------------ MemSet(bWriteBuffer, sizeof(bWriteBuffer), '\0', sizeof(bWriteBuffer)); MemSet(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferSize, '\0', pSmartcardExtension->SmartcardRequest.BufferSize); DebugStatus = SCCMN50M_ExitTransparentMode(pSmartcardExtension); pSmartcardExtension->ReaderExtension->fTransparentMode = FALSE; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = ulReadTotalTimeoutMultiplier; // to be sure that the new settings take effect pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250; DebugStatus = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; if (NT_SUCCESS(DebugStatus)) { DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulStatBytesRead,abStatReadBuffer,sizeof(abStatReadBuffer)); } return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_TransmitT1(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; ULONG ulBytesToWrite; UCHAR bWriteBuffer [256 + T1_HEADER_LEN + MAX_EDC_LEN]; UCHAR bReadBuffer [256 + T1_HEADER_LEN + MAX_EDC_LEN]; ULONG ulBytesRead; ULONG ulBytesStillToRead; /* SmartcardDebug( DEBUG_TRACE, ("%s!CWT = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->CardCapabilities.T1.CWT/1000) ); SmartcardDebug( DEBUG_TRACE, ("%s!BWT = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->CardCapabilities.T1.BWT/1000); ); */ pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = pSmartcardExtension->CardCapabilities.T1.BWT/1000; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = pSmartcardExtension->CardCapabilities.T1.CWT/1000; /* SmartcardDebug(DEBUG_TRACE,("%s!ReadTotalTimeoutConstant = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant)); SmartcardDebug(DEBUG_TRACE,("%s!ReadTotalTimeoutMultiplier = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier)); */ // set T1 protocol flag for CardMan SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_T1); if (pSmartcardExtension->CardCapabilities.T1.EDC == T1_CRC_CHECK) { SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_CRC); } do { pSmartcardExtension->SmartcardRequest.BufferLength = 0; // no bytes additionally needed status = SmartcardT1Request(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitTransmitT1; } ulBytesToWrite = pSmartcardExtension->SmartcardRequest.BufferLength; SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, // Tx conrol (UCHAR)ulBytesToWrite, // Tx length 0, // Rx control T1_HEADER_LEN); // Rx length if (sizeof(bWriteBuffer) < ulBytesToWrite) { status = STATUS_BUFFER_OVERFLOW; goto ExitTransmitT1; } // copy data to the write buffer MemCpy(bWriteBuffer, sizeof(bWriteBuffer), pSmartcardExtension->SmartcardRequest.Buffer, ulBytesToWrite); // write data to card status = SCCMN50M_WriteCardMan (pSmartcardExtension, ulBytesToWrite, bWriteBuffer); if (status == STATUS_SUCCESS) { // read CardMan Header pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (status == STATUS_SUCCESS) { ulBytesStillToRead = bReadBuffer[1]; status = SCCMN50M_ReadCardMan(pSmartcardExtension, ulBytesStillToRead, &ulBytesRead, bReadBuffer, sizeof(bReadBuffer)); if (status == STATUS_SUCCESS) { if (bReadBuffer[1] == T1_WTX_REQUEST) { pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = (ULONG)(1000 +((pSmartcardExtension->CardCapabilities.T1.BWT*bReadBuffer[3])/1000)); SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant)); } else { pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = pSmartcardExtension->CardCapabilities.T1.BWT/1000; SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant)); } // copy received bytes MemCpy(pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferSize, bReadBuffer, ulBytesRead); pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead; } } } if (status != STATUS_SUCCESS) { // reset serial timeout SmartcardDebug( DEBUG_PROTOCOL, ( "%s!reseting timeout constant\n", DRIVER_NAME) ); pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = pSmartcardExtension->CardCapabilities.T1.BWT/1000; SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n", DRIVER_NAME, pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant)); pSmartcardExtension->SmartcardReply.BufferLength = 0L; } // bug fix for smclib if (pSmartcardExtension->T1.State == T1_IFS_RESPONSE && pSmartcardExtension->T1.OriginalState == T1_I_BLOCK) { pSmartcardExtension->T1.State = T1_I_BLOCK; } status = SmartcardT1Reply(pSmartcardExtension); } while (status == STATUS_MORE_PROCESSING_REQUIRED); ExitTransmitT1: // ------------------------------------------ // ITSEC E2 requirements: clear write buffers // ------------------------------------------ MemSet(bWriteBuffer, sizeof(bWriteBuffer), '\0', sizeof(bWriteBuffer)); MemSet(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferSize, '\0', pSmartcardExtension->SmartcardRequest.BufferSize); pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_InitializeSmartcardExtension( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulDeviceInstance ) { // ================================== // Fill the Vendor_Attr structure // ================================== MemCpy(pSmartcardExtension->VendorAttr.VendorName.Buffer, sizeof(pSmartcardExtension->VendorAttr.VendorName.Buffer), ATTR_VENDOR_NAME, sizeof(ATTR_VENDOR_NAME) ); // // Length of vendor name // pSmartcardExtension->VendorAttr.VendorName.Length = sizeof(ATTR_VENDOR_NAME); // // Version number // pSmartcardExtension->VendorAttr.IfdVersion.BuildNumber = IFD_NT_BUILDNUMBER_CARDMAN; pSmartcardExtension->VendorAttr.IfdVersion.VersionMinor = IFD_NT_VERSIONMINOR_CARDMAN; pSmartcardExtension->VendorAttr.IfdVersion.VersionMajor = IFD_NT_VERSIONMAJOR_CARDMAN; MemCpy(pSmartcardExtension->VendorAttr.IfdType.Buffer, sizeof(pSmartcardExtension->VendorAttr.IfdType.Buffer), ATTR_IFD_TYPE_CM, sizeof(ATTR_IFD_TYPE_CM)); // // Length of reader name // pSmartcardExtension->VendorAttr.IfdType.Length = sizeof(ATTR_IFD_TYPE_CM); // // Unit number which is zero based // pSmartcardExtension->VendorAttr.UnitNo = ulDeviceInstance; // ================================================ // Fill the SCARD_READER_CAPABILITIES structure // =============================================== // // Supported protoclols by the reader // pSmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0; // // Reader type serial, keyboard, .... // pSmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_SERIAL; // // Mechanical characteristics like swallows etc. // pSmartcardExtension->ReaderCapabilities.MechProperties = 0; // // Current state of the reader // pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN; // // Data Rate // pSmartcardExtension->ReaderCapabilities.DataRate.Default = pSmartcardExtension->ReaderCapabilities.DataRate.Max = dataRatesSupported[0]; // reader could support higher data rates pSmartcardExtension->ReaderCapabilities.DataRatesSupported.List = dataRatesSupported; pSmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]); // // CLKFrequency // pSmartcardExtension->ReaderCapabilities.CLKFrequency.Default = pSmartcardExtension->ReaderCapabilities.CLKFrequency.Max = CLKFrequenciesSupported[0]; pSmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.List = CLKFrequenciesSupported; pSmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.Entries = sizeof(CLKFrequenciesSupported) / sizeof(CLKFrequenciesSupported[0]); //pSmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 3571; //3.571 MHz //pSmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 3571; //3.571 MHz // // MaxIFSD // pSmartcardExtension->ReaderCapabilities.MaxIFSD = ATTR_MAX_IFSD_CARDMAN_II; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID StrSet(PUCHAR Buffer,ULONG BufferSize,UCHAR Pattern) { ULONG i; for (i=0;i < BufferSize;i++) Buffer[i] = Pattern; return; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID StrCpy(PUCHAR pszDestination,ULONG DestinationLen,PUCHAR pszSrc) { ULONG Len; ULONG SrcLen; ULONG i; StrSet(pszDestination, DestinationLen,'\0'); SrcLen = StrLen(pszSrc); if (DestinationLen - 1 < SrcLen) { Len = DestinationLen - 1; } else { Len = SrcLen; } for (i = 0; i < Len; i++) { pszDestination[i] = pszSrc[i]; if (pszSrc[i] == '\0') break; } return; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ ULONG StrLen (PUCHAR pszString) { ULONG Len = 0; while ( *(pszString+Len) != '\0') Len++; return(Len); } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID StrCat(PUCHAR pszDestination,ULONG DestinationLen,PUCHAR pszSrc) { ULONG Len; ULONG i; ULONG SrcLen; ULONG DestLen; SrcLen = StrLen(pszSrc); DestLen = StrLen(pszDestination); if (StrLen(pszDestination)>=DestinationLen) return; if ((DestinationLen-DestLen-1) < SrcLen) { Len = DestinationLen-DestLen-1; } else { Len = SrcLen; } for (i=0; i < Len; i++) { pszDestination[DestLen+i] = pszSrc[i]; if (pszSrc[i] == '\0') break; } return; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID MemSet(PUCHAR pBuffer, ULONG ulBufferSize, UCHAR ucPattern, ULONG ulCount) { ULONG i; for (i=0; i= ulBufferSize) break; pBuffer[i] = ucPattern; } return ; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID MemCpy(PUCHAR pDestination, ULONG ulDestinationLen, PUCHAR pSource, ULONG ulCount) { ULONG i = 0; while ( ulCount-- && ulDestinationLen-- ) { pDestination[i] = pSource[i]; i++; } return; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_UpdateCurrentStateThread( IN PVOID Context ) { PDEVICE_EXTENSION deviceExtension = Context; PSMARTCARD_EXTENSION smartcardExtension; NTSTATUS status; LONG lRetry; KIRQL oldIrql; LONG ulFailures; BOOLEAN fPriorityIncreased; LONG lOldPriority; SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread started\n",DRIVER_NAME)); ulFailures = 0; smartcardExtension = &deviceExtension->SmartcardExtension; // // Increase priority for first loop, // because state of card must be known for resource manager // fPriorityIncreased=TRUE; lOldPriority=KeSetPriorityThread(KeGetCurrentThread(),HIGH_PRIORITY); do { KeWaitForSingleObject(&smartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); if ( smartcardExtension->ReaderExtension->TimeToTerminateThread ) { KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE); smartcardExtension->ReaderExtension->TimeToTerminateThread = FALSE; PsTerminateSystemThread( STATUS_SUCCESS ); } lRetry = 1; do { //SmartcardDebug(DEBUG_TRACE,( "%s!*.",DRIVER_NAME)); status=SCCMN50M_UpdateCurrentState(smartcardExtension); if (NT_SUCCESS(status)) { break; } else { lRetry--; } } while (lRetry >= 0); if (lRetry < 0) { ulFailures++; if (ulFailures == 1) { SmartcardDebug( DEBUG_DRIVER, ( "%s!CardMan removed\n", DRIVER_NAME) ); // issue a card removal event if reader has been removed if (smartcardExtension->ReaderExtension->ulOldCardState == INSERTED || smartcardExtension->ReaderExtension->ulOldCardState == POWERED ) { SmartcardDebug( DEBUG_DRIVER, ( "%s!issuing card removal event\n", DRIVER_NAME) ); SCCMN50M_CompleteCardTracking(smartcardExtension); smartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested = TRUE; smartcardExtension->ReaderExtension->ulNewCardState = REMOVED; smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState; smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; smartcardExtension->CardCapabilities.ATR.Length = 0; SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS); smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0; smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0; } } if (ulFailures == 3) { // remove the device and terminate this thread if (KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l) { SmartcardDebug( DEBUG_DRIVER, ( "%s!closing serial driver\n", DRIVER_NAME) ); SCCMN50M_CloseSerialDriver(smartcardExtension->OsData->DeviceObject); KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE); smartcardExtension->ReaderExtension->TimeToTerminateThread = FALSE; smartcardExtension->ReaderExtension->ThreadObjectPointer = NULL; PsTerminateSystemThread( STATUS_SUCCESS ); } } } else { ulFailures = 0; } KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE); if (fPriorityIncreased) { fPriorityIncreased=FALSE; KeSetPriorityThread(KeGetCurrentThread(),lOldPriority); // // Lower ourselves down just at tad so that we compete a // little less. // KeSetBasePriorityThread(KeGetCurrentThread(),-1); } //SmartcardDebug(DEBUG_TRACE,( "...#\n")); Wait (smartcardExtension,500 * ms_); } while (TRUE); } NTSTATUS SCCMN50M_UpdateCurrentState( IN PSMARTCARD_EXTENSION smartcardExtension ) { NTSTATUS NTStatus; UCHAR pbReadBuffer[2]; ULONG ulBytesRead; BOOLEAN fCardStateChanged; fCardStateChanged = FALSE; SCCMN50M_ClearCardManHeader(smartcardExtension); smartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250; NTStatus = SCCMN50M_WriteCardMan(smartcardExtension,0,NULL); smartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; if (NT_SUCCESS(NTStatus)) { NTStatus = SCCMN50M_ReadCardMan(smartcardExtension,2,&ulBytesRead,pbReadBuffer,sizeof(pbReadBuffer)); if (ulBytesRead == 0x02 && // two bytes must have benn received (pbReadBuffer[0] & 0x0F) && // at least one version bit must be set ((pbReadBuffer[0] & 0x09) == 0x00)) // Bit 0 and Bit 3 must be 0 { if ((pbReadBuffer[0] & 0x04) == 0x04 && (pbReadBuffer[0] & 0x02) == 0x02) smartcardExtension->ReaderExtension->ulNewCardState = INSERTED; if ((pbReadBuffer[0] & 0x04) == 0x00 && (pbReadBuffer[0] & 0x02) == 0x02) smartcardExtension->ReaderExtension->ulNewCardState = REMOVED; if ((pbReadBuffer[0] & 0x04) == 0x04 && (pbReadBuffer[0] & 0x02) == 0x00) smartcardExtension->ReaderExtension->ulNewCardState = POWERED; //SmartcardDebug(DEBUG_TRACE,("old %x ",smartcardExtension->ReaderExtension->ulOldCardState )); //SmartcardDebug(DEBUG_TRACE,("new %x\n",smartcardExtension->ReaderExtension->ulNewCardState )); if (smartcardExtension->ReaderExtension->ulNewCardState == INSERTED && smartcardExtension->ReaderExtension->ulOldCardState == POWERED ) { // card has been removed and reinserted within 500ms fCardStateChanged = TRUE; SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard removed and reinserted\n",DRIVER_NAME)); smartcardExtension->ReaderExtension->ulOldCardState = REMOVED; smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; // clear any cardspecific data smartcardExtension->CardCapabilities.ATR.Length = 0; SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS); smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0; smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0; } 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!Smartcard removed\n",DRIVER_NAME)); smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState; smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; // clear any cardspecific data smartcardExtension->CardCapabilities.ATR.Length = 0; SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS); smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0; smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0; } if (smartcardExtension->ReaderExtension->ulNewCardState == INSERTED && (smartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN || smartcardExtension->ReaderExtension->ulOldCardState == REMOVED ) ) { // card has been inserted fCardStateChanged = TRUE; SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard inserted\n",DRIVER_NAME)); smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState; smartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; } // state after reset of the PC (only for CardMan Power+ possible) if (smartcardExtension->ReaderExtension->ulNewCardState == POWERED && smartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN ) { // card has been inserted fCardStateChanged = TRUE; SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard inserted (and powered)\n",DRIVER_NAME)); smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState; smartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; } if (smartcardExtension->ReaderExtension->ulNewCardState == POWERED && smartcardExtension->ReaderExtension->ulOldCardState == INSERTED ) { smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState; } // complete IOCTL_SMARTCARD_IS_ABSENT or IOCTL_SMARTCARD_IS_PRESENT if (fCardStateChanged == TRUE && smartcardExtension->OsData->NotificationIrp ) { SCCMN50M_CompleteCardTracking(smartcardExtension); } } } return NTStatus; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS Wait (PSMARTCARD_EXTENSION pSmartcardExtension,ULONG ulMilliseconds) { NTSTATUS status = STATUS_SUCCESS; LARGE_INTEGER WaitTime; WaitTime = RtlConvertLongToLargeInteger(ulMilliseconds * WAIT_MS); KeDelayExecutionThread(KernelMode,FALSE,&WaitTime); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_SetSCRControlFlags( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN UCHAR Flags ) { pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl |= Flags; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_ClearSCRControlFlags( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN UCHAR Flags ) { pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl &= ~Flags; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_SetCardControlFlags( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN UCHAR Flags ) { pSmartcardExtension->ReaderExtension->CardManConfig.CardControl |= Flags; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_ClearCardControlFlags( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN UCHAR Flags ) { pSmartcardExtension->ReaderExtension->CardManConfig.CardControl &= ~Flags; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_ClearCardManHeader( IN PSMARTCARD_EXTENSION pSmartcardExtension ) { pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = 0x00; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_SetCardManHeader( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN UCHAR TxControl, IN UCHAR TxLength, IN UCHAR RxControl, IN UCHAR RxLength ) { pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = TxControl; pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = TxLength; pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = RxControl; pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = RxLength; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_WriteCardMan ( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBytesToWrite, IN PUCHAR pbWriteBuffer ) { NTSTATUS status; NTSTATUS DebugStatus; PSERIAL_STATUS pSerialStatus; // =============================================== // Set up timeouts for following read operation // =============================================== pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts, sizeof(SERIAL_TIMEOUTS)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS); pSmartcardExtension->SmartcardReply.BufferLength = 0; /* SmartcardDebug(DEBUG_TRACE,("ReadTotalTimeoutMultiplier = %ld\n", pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier)); SmartcardDebug(DEBUG_TRACE,("ReadTotalTimeoutConstant = %ld\n", pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant)); */ status = SCCMN50M_SerialIo(pSmartcardExtension); // =============================================== // write to the CardMan // =============================================== DebugStatus = SCCMN50M_SetWrite(pSmartcardExtension,ulBytesToWrite,pbWriteBuffer); // add pseudoboost (0x00) to write buffer for CardManII if (pSmartcardExtension->ReaderExtension->fTransparentMode == FALSE ) { pSmartcardExtension->SmartcardRequest.Buffer[pSmartcardExtension->SmartcardRequest.BufferLength] = 0x00; pSmartcardExtension->SmartcardRequest.BufferLength++; } status = SCCMN50M_SerialIo(pSmartcardExtension); // overwrite write buffer with '@' RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferLength, '@'); // =============================================== // error checking // =============================================== DebugStatus = SCCMN50M_GetCommStatus(pSmartcardExtension); pSerialStatus = (PSERIAL_STATUS) pSmartcardExtension->SmartcardReply.Buffer; if (pSerialStatus->Errors || NT_ERROR(status)) { pSmartcardExtension->ReaderExtension->SerialErrors = pSerialStatus->Errors; if (!pSmartcardExtension->ReaderExtension->fTransparentMode ) DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension); goto ExitSCCMN50M_WriteCardMan; } ExitSCCMN50M_WriteCardMan: if (status != STATUS_SUCCESS) { SmartcardDebug( DEBUG_TRACE, ( "%s!WriteCardMan: Failed, exit %lx\n", DRIVER_NAME,status) ); } return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ResyncCardManI (IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; // SmartcardDebug(DEBUG_TRACE,("%s!ResyncCardManI: Enter\n",DRIVER_NAME)) // clear error flags pSmartcardExtension->ReaderExtension->SerialErrors = 0; // clear any pending errors status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } // clear COM buffers status = SCCMN50M_PurgeComm(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } // #################################################################### // set break if (!pSmartcardExtension->ReaderExtension->fTransparentMode) { status = SCCMN50M_SetBRK(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SetBreak failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } } // wait 1ms Wait(pSmartcardExtension,1 * ms_); // clear RTS status = SCCMN50M_ClearRTS(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ClearRTS failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } // wait 2ms Wait(pSmartcardExtension,2 * ms_); // set RTS status = SCCMN50M_SetRTS(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_SetRTS failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } // wait 1ms Wait(pSmartcardExtension,1 * ms_); // clear break if (!pSmartcardExtension->ReaderExtension->fTransparentMode) { pSmartcardExtension->ReaderExtension->BreakSet = FALSE; status = SCCMN50M_ClearBRK(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("ClearBreak failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManI; } } // #################################################################### // next write operation must send config data pSmartcardExtension->ReaderExtension->NoConfig = FALSE; // clear COM buffers status = SCCMN50M_PurgeComm(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitSCCMN50M_ResyncCardManI; } // clear any pending errors status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitSCCMN50M_ResyncCardManI; } ExitSCCMN50M_ResyncCardManI: //SmartcardDebug(DEBUG_TRACE,("%s!ResyncCardManI: Exit %lx\n",DRIVER_NAME,status)) return status; } NTSTATUS SCCMN50M_ResyncCardManII (IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; SmartcardDebug( DEBUG_TRACE, ( "%s!ResyncCardManII: Enter\n", DRIVER_NAME) ); // clear error flags pSmartcardExtension->ReaderExtension->SerialErrors = 0; // clear any pending errors status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManII; } // clear COM buffers status = SCCMN50M_PurgeComm(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManII; } // 150 * 0xFE RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer,150,0xFE); pSmartcardExtension->SmartcardRequest.Buffer[150] = 0x00; pSmartcardExtension->SmartcardRequest.BufferLength = 151; pSmartcardExtension->SmartcardReply.BufferLength = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { Wait(pSmartcardExtension,2 * ms_); // try resync once more // clear error flags pSmartcardExtension->ReaderExtension->SerialErrors = 0; // clear any pending errors status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManII; } // clear COM buffers status = SCCMN50M_PurgeComm(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManII; } // 150 * 0xFE RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer,150,0xFE); pSmartcardExtension->SmartcardRequest.Buffer[150] = 0x00; pSmartcardExtension->SmartcardRequest.BufferLength = 151; pSmartcardExtension->SmartcardReply.BufferLength = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE; status = SCCMN50M_SerialIo(pSmartcardExtension); if (status != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_SerialIo failed ! status = %x\n",status)) goto ExitSCCMN50M_ResyncCardManII; } // normally the second resync command is always successful } // clear COM buffers status = SCCMN50M_PurgeComm(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitSCCMN50M_ResyncCardManII; } // clear any pending errors status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitSCCMN50M_ResyncCardManII; } ExitSCCMN50M_ResyncCardManII: SmartcardDebug( DEBUG_TRACE, ( "%s!ResyncCardManII: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SerialIo(IN PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; IO_STATUS_BLOCK ioStatus; KEVENT event; PIRP irp; PIO_STACK_LOCATION irpNextStack; PUCHAR pbRequestBuffer; PUCHAR pbReplyBuffer; ULONG ulRequestBufferLength; ULONG ulReplyBufferLength ; // // Check if the buffers are large enough // ASSERT(pSmartcardExtension->SmartcardReply.BufferLength <= pSmartcardExtension->SmartcardReply.BufferSize); ASSERT(pSmartcardExtension->SmartcardRequest.BufferLength <= pSmartcardExtension->SmartcardRequest.BufferSize); if (pSmartcardExtension->SmartcardReply.BufferLength > pSmartcardExtension->SmartcardReply.BufferSize || pSmartcardExtension->SmartcardRequest.BufferLength > pSmartcardExtension->SmartcardRequest.BufferSize) { SmartcardLogError(pSmartcardExtension->OsData->DeviceObject, SCCMN50M_BUFFER_TOO_SMALL, NULL, 0); return STATUS_BUFFER_TOO_SMALL; } // set pointer and length of request and reply buffer ulRequestBufferLength = pSmartcardExtension->SmartcardRequest.BufferLength; pbRequestBuffer = (ulRequestBufferLength ? pSmartcardExtension->SmartcardRequest.Buffer : NULL); pbReplyBuffer = pSmartcardExtension->SmartcardReply.Buffer; ulReplyBufferLength = pSmartcardExtension->SmartcardReply.BufferLength; KeInitializeEvent(&event, NotificationEvent, FALSE); // // Build irp to be sent to serial driver // irp = IoBuildDeviceIoControlRequest(pSmartcardExtension->ReaderExtension->SerialIoControlCode, pSmartcardExtension->ReaderExtension->AttachedDeviceObject, pbRequestBuffer, ulRequestBufferLength, pbReplyBuffer, ulReplyBufferLength, FALSE, &event, &ioStatus); ASSERT(irp != NULL); if (irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } irpNextStack = IoGetNextIrpStackLocation(irp); switch (pSmartcardExtension->ReaderExtension->SerialIoControlCode) { // // The serial driver transfers data from/to irp->AssociatedIrp.SystemBuffer // case SMARTCARD_WRITE: irpNextStack->MajorFunction = IRP_MJ_WRITE; irpNextStack->Parameters.Write.Length = pSmartcardExtension->SmartcardRequest.BufferLength; break; case SMARTCARD_READ: irpNextStack->MajorFunction = IRP_MJ_READ; irpNextStack->Parameters.Read.Length = pSmartcardExtension->SmartcardReply.BufferLength; break; } status = IoCallDriver(pSmartcardExtension->ReaderExtension->AttachedDeviceObject,irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); status = ioStatus.Status; } switch (pSmartcardExtension->ReaderExtension->SerialIoControlCode) { case SMARTCARD_READ: if (status == STATUS_TIMEOUT) { SmartcardDebug(DEBUG_ERROR, ("%s!Timeout while reading from CardMan\n", DRIVER_NAME)); // // STATUS_TIMEOUT isn't correctly mapped // to a WIN32 error, that's why we change it here // to STATUS_IO_TIMEOUT // status = STATUS_IO_TIMEOUT; pSmartcardExtension->SmartcardReply.BufferLength = 0; } break; } #if 0 if (status != STATUS_SUCCESS) { SmartcardDebug(DEBUG_DRIVER, ("%s!SerialIo = %lx\n", DRIVER_NAME, status)); } #endif return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ReadCardMan ( IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG BytesToRead, OUT PULONG pBytesRead, IN PUCHAR pReadBuffer, IN ULONG ReadBufferSize ) { NTSTATUS status; NTSTATUS DebugStatus; BOOLEAN fRc; // check if read buffer is large enough ASSERT(BytesToRead <= ReadBufferSize); *pBytesRead = 0; // default setting DebugStatus = SCCMN50M_SetRead(pSmartcardExtension,BytesToRead); // // read operation // status = SCCMN50M_SerialIo(pSmartcardExtension); if (status == STATUS_SUCCESS) { *pBytesRead = pSmartcardExtension->SmartcardReply.BufferLength; MemCpy(pReadBuffer, ReadBufferSize, pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferLength); // overwrite read buffer with '@' MemSet(pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferSize, '@', pSmartcardExtension->SmartcardReply.BufferLength); } if (status != STATUS_SUCCESS || SCCMN50M_IOOperationFailed(pSmartcardExtension)) { if (!pSmartcardExtension->ReaderExtension->fTransparentMode) { DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension); } goto ExitSCCMN50M_ReadCardMan; } // ***************************************** // set CardManII to state RH Config // ***************************************** // don't set CardMan to RH config if there are still bytes to be read if (pSmartcardExtension->ReaderExtension->ToRHConfig == TRUE) { pSmartcardExtension->SmartcardReply.BufferLength = 0; pSmartcardExtension->SmartcardRequest.Buffer [0] = 0x00; pSmartcardExtension->SmartcardRequest.Buffer [1] = 0x00; pSmartcardExtension->SmartcardRequest.Buffer [2] = 0x00; pSmartcardExtension->SmartcardRequest.Buffer [3] = 0x00; pSmartcardExtension->SmartcardRequest.Buffer [4] = 0x89; pSmartcardExtension->SmartcardRequest.BufferLength = 5; pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE; status = SCCMN50M_SerialIo(pSmartcardExtension); if (status != STATUS_SUCCESS || SCCMN50M_IOOperationFailed(pSmartcardExtension)) { DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension); goto ExitSCCMN50M_ReadCardMan; } } ExitSCCMN50M_ReadCardMan: // set default value; pSmartcardExtension->ReaderExtension->ToRHConfig = TRUE; if (status != STATUS_SUCCESS) { SmartcardDebug( DEBUG_TRACE, ( "%s!ReadCardMan: Failed, exit %lx\n", DRIVER_NAME,status) ); } return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_GetCommStatus ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { PSERIAL_READER_CONFIG configData = &SmartcardExtension->ReaderExtension->SerialConfigData; NTSTATUS status; PUCHAR request = SmartcardExtension->SmartcardRequest.Buffer; SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize; SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_GET_COMMSTATUS; SmartcardExtension->SmartcardRequest.Buffer = (PUCHAR) &configData->SerialStatus; SmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_STATUS); status = SCCMN50M_SerialIo(SmartcardExtension); // // restore pointer to original request buffer // SmartcardExtension->SmartcardRequest.Buffer = request; return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ BOOLEAN SCCMN50M_IOOperationFailed(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS DebugStatus; PSERIAL_STATUS pSerialStatus; DebugStatus = SCCMN50M_GetCommStatus(pSmartcardExtension); pSerialStatus = (PSERIAL_STATUS)pSmartcardExtension->SmartcardReply.Buffer; if (pSerialStatus->Errors) return TRUE; else return FALSE; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_PurgeComm (IN PSMARTCARD_EXTENSION pSmartcardExtension ) { PSERIAL_READER_CONFIG configData = &pSmartcardExtension->ReaderExtension->SerialConfigData; NTSTATUS status; PUCHAR request = pSmartcardExtension->SmartcardRequest.Buffer; pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_PURGE; pSmartcardExtension->SmartcardRequest.Buffer = (PUCHAR) &configData->PurgeMask; pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(ULONG); status = SCCMN50M_SerialIo(pSmartcardExtension); // // restore pointer to original request buffer // pSmartcardExtension->SmartcardRequest.Buffer = request; // under W2000 & CardMan P+ STATUS_CANCELLED may be returned if (status == STATUS_CANCELLED) status = STATUS_SUCCESS; return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetRead(IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBytesToRead ) { pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_READ; pSmartcardExtension->SmartcardRequest.BufferLength = 0; pSmartcardExtension->SmartcardReply.BufferLength = ulBytesToRead; return STATUS_SUCCESS; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetWrite(IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG BytesToWrite, IN PUCHAR WriteBuffer ) { ULONG Offset = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE; pSmartcardExtension->SmartcardReply.BufferLength = 0; if (pSmartcardExtension->ReaderExtension->fTransparentMode == FALSE) { // send always config string for CardManII, expect we set it manualy // to NoConfig = TRUE. (note: only one time) if (pSmartcardExtension->ReaderExtension->NoConfig == FALSE) { MemCpy(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferSize, (PUCHAR)&pSmartcardExtension->ReaderExtension->CardManConfig, sizeof(CARDMAN_CONFIG)); Offset = 4; } else { pSmartcardExtension->ReaderExtension->NoConfig = FALSE; } MemCpy(pSmartcardExtension->SmartcardRequest.Buffer + Offset, pSmartcardExtension->SmartcardRequest.BufferSize, (PUCHAR)&pSmartcardExtension->ReaderExtension->CardManHeader, sizeof(CARDMAN_HEADER)); Offset+=4; } if (BytesToWrite != 0) { MemCpy(pSmartcardExtension->SmartcardRequest.Buffer + Offset, pSmartcardExtension->SmartcardRequest.BufferSize, WriteBuffer, BytesToWrite); } pSmartcardExtension->SmartcardRequest.BufferLength = Offset + BytesToWrite; return STATUS_SUCCESS; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_StartCardTracking( PDEVICE_EXTENSION pDeviceExtension ) { NTSTATUS status; HANDLE hThread; PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->SmartcardExtension; SmartcardDebug(DEBUG_TRACE, ("%s!StartCardTracking: Enter\n",DRIVER_NAME)); KeWaitForSingleObject(&pSmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); // create thread for updating current state status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, SCCMN50M_UpdateCurrentStateThread, pDeviceExtension); if (!NT_ERROR(status)) { // // We've got the thread. Now get a pointer to it. // status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, &pSmartcardExtension->ReaderExtension->ThreadObjectPointer, NULL); if (NT_ERROR(status)) { pSmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE; } else { // // Now that we have a reference to the thread // we can simply close the handle. // ZwClose(hThread); } } else { } // Release the mutex KeReleaseMutex(&pSmartcardExtension->ReaderExtension->CardManIOMutex, FALSE); SmartcardDebug(DEBUG_TRACE, ("%s!StartCardTracking: Exit %lx\n",DRIVER_NAME,status)); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_InitCommPort (PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; SmartcardDebug( DEBUG_TRACE, ( "%s!InitCommPort: Enter\n", DRIVER_NAME) ); // =============================== // clear any pending errors // =============================== status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status)) goto ExitInitCommPort; } // ============================== // set baudrate for CardMan // ============================== pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate, sizeof(SERIAL_BAUD_RATE)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status)) goto ExitInitCommPort; } // =============================== // set comm timeouts // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = DEFAULT_READ_INTERVAL_TIMEOUT; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutConstant = DEFAULT_WRITE_TOTAL_TIMEOUT_CONSTANT; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutMultiplier = DEFAULT_WRITE_TOTAL_TIMEOUT_MULTIPLIER; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts, sizeof(SERIAL_TIMEOUTS)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_TIMEOUTS failed ! status = %x\n",status)) goto ExitInitCommPort; } // =============================== // set line control // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 8; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status)) goto ExitInitCommPort; } // =============================== // Set handflow // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XonLimit = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XoffLimit = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.FlowReplace = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.ControlHandShake = SERIAL_ERROR_ABORT | SERIAL_DTR_CONTROL; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_HANDFLOW; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow, sizeof(SERIAL_HANDFLOW)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_HANDFLOW); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_HANDFLOW failed ! status = %x\n",status)) goto ExitInitCommPort; } // =============================== // set purge mask // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.PurgeMask = SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT | SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR; // =============================== // set DTR // =============================== status = SCCMN50M_SetDTR(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_DRT failed ! status = %x\n",status)) goto ExitInitCommPort; } // =============================== // set RTS // =============================== status = SCCMN50M_SetRTS(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status)) goto ExitInitCommPort; } ExitInitCommPort: SmartcardDebug( DEBUG_TRACE, ( "%s!InitCommPort: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetDTR(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; pSmartcardExtension->SmartcardReply.BufferLength = 0; pSmartcardExtension->SmartcardRequest.BufferLength = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_DTR; status = SCCMN50M_SerialIo(pSmartcardExtension); // under W2000 & CardMan P+ STATUS_CANCELLED may be returned if (status == STATUS_CANCELLED) status = STATUS_SUCCESS; return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetRTS(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize; pSmartcardExtension->SmartcardRequest.BufferLength = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_RTS; status = SCCMN50M_SerialIo(pSmartcardExtension); // under W2000 & CardMan P+ STATUS_CANCELLED may be returned if (status == STATUS_CANCELLED) status = STATUS_SUCCESS; return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_InitializeCardMan(IN PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; UCHAR pReadBuffer[2]; ULONG ulBytesRead; BOOLEAN fCardManFound = FALSE; PREADER_EXTENSION readerExtension = pSmartcardExtension->ReaderExtension; ULONG ulRetries; SmartcardDebug( DEBUG_TRACE, ( "%s!InitializeCardMan: Enter\n", DRIVER_NAME) ); pSmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN; // ============================================== // CardManII // ============================================== pSmartcardExtension->ReaderExtension->NoConfig = FALSE; pSmartcardExtension->ReaderExtension->ToRHConfig = TRUE; // This waiting time if necessary for CardMan Power+, because // the pnP string may be dumped Wait(pSmartcardExtension,200); status = SCCMN50M_InitCommPort(pSmartcardExtension); if (status != STATUS_SUCCESS) goto ExitInitializeCardMan; // // init CommPort was O.K. // now try to find a reader // // To be sure wait make an additional wait Wait(pSmartcardExtension,100); status = SCCMN50M_ResyncCardManII(pSmartcardExtension); status = SCCMN50M_ResyncCardManII(pSmartcardExtension); // no data except config + header pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl = XMIT_HANDSHAKE_OFF; pSmartcardExtension->ReaderExtension->CardManConfig.CardControl = 0x00; pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x00; pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = 0x00; pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = 0x00; status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status == STATUS_SUCCESS) { status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,pReadBuffer,sizeof(pReadBuffer)); if (status == STATUS_SUCCESS && ulBytesRead == 0x02 && // two bytes received pReadBuffer[0] >= 0x40 && // at least one version bit must be set pReadBuffer[1] == 0x00 && ((pReadBuffer[0] & 0x09) == 0) ) // bit 0 and 3 must be cleared { pSmartcardExtension->ReaderExtension->ulFWVersion = (pReadBuffer[0] >> 4) * 30 + 120; pSmartcardExtension->ReaderExtension->fSPESupported = FALSE; SmartcardDebug( DEBUG_DRIVER, ( "%s!CardMan (FW %ld) found\n", DRIVER_NAME,pSmartcardExtension->ReaderExtension->ulFWVersion) ); fCardManFound = TRUE; } } ExitInitializeCardMan: if (fCardManFound == TRUE) status = STATUS_SUCCESS; else status = STATUS_UNSUCCESSFUL; SmartcardDebug( DEBUG_TRACE, ( "%s!InitializeCardMan: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_EnterTransparentMode (IN PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; SmartcardDebug(DEBUG_TRACE,("EnterTransparentMode : enter\n")); // Step 1 : Resync CardMan by RTS usage status = SCCMN50M_ResyncCardManI(pSmartcardExtension); if (status != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManI failed ! status = %ld\n",status)) goto ExitEnterTransparentMode; } // Step 2 : set baud rate to 9600 pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 9600; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate, sizeof(SERIAL_BAUD_RATE)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status)) goto ExitEnterTransparentMode; } ExitEnterTransparentMode: // Step 3 : set ATR and DUMP_BUFFER flags // During normal operation these two flags can never be set at the same time SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | TO_STATE_XH); SmartcardDebug(DEBUG_TRACE,("EnterTransparentMode : exit\n")); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ExitTransparentMode (IN PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; SmartcardDebug(DEBUG_TRACE,("ExitTransparentMode : enter\n")); // =============================== // clear any pending errors // =============================== status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status)) goto ExitExitTransparentMode; } // Step 1 : Resync CardMan by RTS usage status = SCCMN50M_ResyncCardManI(pSmartcardExtension); if (status != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManI failed ! status = %ld\n",status)) goto ExitExitTransparentMode; } // Step 2 : set baud rate to 38400 pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate, sizeof(SERIAL_BAUD_RATE)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status)) goto ExitExitTransparentMode; } // if the inserted card uses inverse convention , we must now switch the COM port // back to even parity if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status)) goto ExitExitTransparentMode; } } ExitExitTransparentMode: // Step 3 : set ATR and DUMP_BUFFER flags // During normal operation these two flags can never be set at the same time SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | TO_STATE_XH); status = SCCMN50M_ResyncCardManII(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManII failed ! status = %x\n",status)) goto ExitExitTransparentMode; } SmartcardDebug(DEBUG_TRACE,("ExitTransparentMode : exit\n")); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ClearRTS(IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status; SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize; SmartcardExtension->SmartcardRequest.BufferLength = 0; SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_CLR_RTS; status = SCCMN50M_SerialIo(SmartcardExtension); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_IoCtlVendor(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS DebugStatus; UCHAR pbAttrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength; SmartcardDebug( DEBUG_TRACE, ( "%s!IoCtlVendor : Enter\n", DRIVER_NAME) ); switch (pSmartcardExtension->MajorIoControlCode) { case CM_IOCTL_SET_READER_9600_BAUD: status = SCCMN50M_SetFl_1Dl_1(pSmartcardExtension); break; case CM_IOCTL_SET_READER_38400_BAUD: status = SCCMN50M_SetFl_1Dl_3(pSmartcardExtension); break; case CM_IOCTL_CR80S_SAMOS_SET_HIGH_SPEED: status = SCCMN50M_SetHighSpeed_CR80S_SAMOS(pSmartcardExtension); break; case CM_IOCTL_GET_FW_VERSION: status = SCCMN50M_GetFWVersion(pSmartcardExtension); break; case CM_IOCTL_READ_DEVICE_DESCRIPTION: status = SCCMN50M_ReadDeviceDescription(pSmartcardExtension); break; case CM_IOCTL_SET_SYNC_PARAMETERS : status = SCCMN50M_SetSyncParameters(pSmartcardExtension); break; case CM_IOCTL_3WBP_TRANSFER : // for SLE4428 status = SCCMN50M_Transmit3WBP(pSmartcardExtension); break; case CM_IOCTL_2WBP_TRANSFER : // for SLE4442 status = SCCMN50M_Transmit2WBP(pSmartcardExtension); break; case CM_IOCTL_2WBP_RESET_CARD: // SLE4442 Reset Card status = SCCMN50M_ResetCard2WBP(pSmartcardExtension); break; case CM_IOCTL_SYNC_CARD_POWERON: status = SCCMN50M_SyncCardPowerOn(pSmartcardExtension); break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } SmartcardDebug( DEBUG_TRACE, ( "%s!IoCtlVendor : Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetFl_1Dl_3(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS DebugStatus; SmartcardDebug(DEBUG_TRACE, ("%s!SetFl_1Dl_3 Enter\n", DRIVER_NAME)); // check if T=1 active if (pSmartcardExtension->CardCapabilities.Protocol.Selected != SCARD_PROTOCOL_T1) { status = STATUS_CTL_FILE_NOT_SUPPORTED; goto ExitSetFl_1Dl_3; } // Fl=1 // Dl=3 // => 38400 Baud for 3.72 MHz SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ | ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ_FAST); ExitSetFl_1Dl_3: *pSmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetFl_1Dl_3 Exit\n", DRIVER_NAME)); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetFl_1Dl_1(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status = STATUS_SUCCESS; SmartcardDebug(DEBUG_TRACE, ("%s!SetFl_1Dl_1 Enter\n", DRIVER_NAME)); // Fl=1 // Dl=1 // => 9600 for 3.72 MHz SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ | ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); *pSmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetFl_1Dl_1 Exit\n", DRIVER_NAME)); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_GetFWVersion (IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status = STATUS_SUCCESS; SmartcardDebug( DEBUG_TRACE, ( "%s!GetFWVersion : Enter\n", DRIVER_NAME) ); if (pSmartcardExtension->IoRequest.ReplyBufferLength < sizeof (ULONG)) { status = STATUS_BUFFER_OVERFLOW; goto ExitGetFWVersion; } else { *(PULONG)(pSmartcardExtension->IoRequest.ReplyBuffer) = pSmartcardExtension->ReaderExtension->ulFWVersion; } ExitGetFWVersion: *pSmartcardExtension->IoRequest.Information = sizeof(ULONG); SmartcardDebug( DEBUG_TRACE, ( "%s!GetFWVersion : Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ReadDeviceDescription(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status = STATUS_SUCCESS; SmartcardDebug( DEBUG_TRACE, ( "%s!ReadDeviceDescription : Enter\n", DRIVER_NAME) ); if (pSmartcardExtension->IoRequest.ReplyBufferLength < sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription)) { status = STATUS_BUFFER_OVERFLOW; *pSmartcardExtension->IoRequest.Information = 0L; goto ExitReadDeviceDescription; } else { if (pSmartcardExtension->ReaderExtension->abDeviceDescription[0] == 0x00 && pSmartcardExtension->ReaderExtension->abDeviceDescription[1] == 0x00 ) { status = SCCMN50M_GetDeviceDescription(pSmartcardExtension); } if (status == STATUS_SUCCESS) { StrCpy(pSmartcardExtension->IoRequest.ReplyBuffer, pSmartcardExtension->IoRequest.ReplyBufferLength, pSmartcardExtension->ReaderExtension->abDeviceDescription); *pSmartcardExtension->IoRequest.Information = StrLen(pSmartcardExtension->ReaderExtension->abDeviceDescription) +1; } else { MemSet(pSmartcardExtension->ReaderExtension->abDeviceDescription, sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription), 0x00, sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription)); *pSmartcardExtension->IoRequest.Information = 0; } } ExitReadDeviceDescription: SmartcardDebug( DEBUG_TRACE, ( "%s!ReadDeviceDescription : Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetHighSpeed_CR80S_SAMOS (IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; NTSTATUS DebugStatus; UCHAR bReadBuffer[16]; ULONG ulBytesRead; BYTE bCR80S_SAMOS_SET_HIGH_SPEED[4] = {0xFF,0x11,0x94,0x7A}; ULONG ulAtrLength; BYTE bAtr[MAXIMUM_ATR_LENGTH]; SmartcardDebug( DEBUG_TRACE, ( "%s!SetHighSpeed_CR80S_SAMOS : Enter\n", DRIVER_NAME) ); SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_SYN | ENABLE_T0 | ENABLE_T1 ); SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, // Tx control sizeof(bCR80S_SAMOS_SET_HIGH_SPEED), // Tx length 0, // Rx control sizeof(bCR80S_SAMOS_SET_HIGH_SPEED)); // Rx length status = SCCMN50M_WriteCardMan(pSmartcardExtension, sizeof(bCR80S_SAMOS_SET_HIGH_SPEED), bCR80S_SAMOS_SET_HIGH_SPEED); if (status != STATUS_SUCCESS) goto ExitSetHighSpeed; pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (status != STATUS_SUCCESS) goto ExitSetHighSpeed; if (bReadBuffer[1] > sizeof(bReadBuffer)) { status = STATUS_BUFFER_OVERFLOW; goto ExitSetHighSpeed; } status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (status != STATUS_SUCCESS) goto ExitSetHighSpeed; // if the card has accepted this string , the string is echoed if (bReadBuffer[0] == bCR80S_SAMOS_SET_HIGH_SPEED[0] && bReadBuffer[1] == bCR80S_SAMOS_SET_HIGH_SPEED[1] && bReadBuffer[2] == bCR80S_SAMOS_SET_HIGH_SPEED[2] && bReadBuffer[3] == bCR80S_SAMOS_SET_HIGH_SPEED[3] ) { SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ | ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ_FAST); } else { DebugStatus = SCCMN50M_PowerOff(pSmartcardExtension); DebugStatus = SCCMN50M_PowerOn(pSmartcardExtension,&ulAtrLength,bAtr,sizeof(bAtr)); status = STATUS_UNSUCCESSFUL; } ExitSetHighSpeed: *pSmartcardExtension->IoRequest.Information = 0L; SmartcardDebug( DEBUG_TRACE, ( "%s!SetHighSpeed_CR80S_SAMOS : Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetBRK(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize; pSmartcardExtension->SmartcardRequest.BufferLength = 0; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BREAK_ON; status = SCCMN50M_SerialIo(pSmartcardExtension); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ClearBRK(IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS status; SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize; SmartcardExtension->SmartcardRequest.BufferLength = 0; SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BREAK_OFF; status = SCCMN50M_SerialIo(SmartcardExtension); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetProtocol(PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; NTSTATUS DebugStatus; ULONG ulNewProtocol; UCHAR abPTSRequest[4]; UCHAR abReadBuffer[6]; UCHAR abPTSReply [4]; ULONG ulBytesRead; UCHAR bTemp; ULONG ulPtsType; ULONG ulPTSReplyLength=0; ULONG ulStatBytesRead; BYTE abStatReadBuffer[2]; SmartcardDebug( DEBUG_TRACE, ( "%s!SetProtocol : Enter\n", DRIVER_NAME) ); // // 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 ((pSmartcardExtension->CardCapabilities.Protocol.Selected & pSmartcardExtension->MinorIoControlCode)) { status = STATUS_SUCCESS; goto ExitSetProtocol; } ulNewProtocol = pSmartcardExtension->MinorIoControlCode; ulPtsType = PTS_TYPE_OPTIMAL; // we are not sure if we need this at all pSmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_OPTIMAL; while (TRUE) { // set initial character of PTS abPTSRequest[0] = 0xFF; // set the format character if (pSmartcardExtension->CardCapabilities.Protocol.Supported & ulNewProtocol & SCARD_PROTOCOL_T1) { // select T=1 and indicate that PTS1 follows abPTSRequest[1] = 0x11; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1; } else if (pSmartcardExtension->CardCapabilities.Protocol.Supported & ulNewProtocol & SCARD_PROTOCOL_T0) { // select T=1 and indicate that PTS1 follows abPTSRequest[1] = 0x10; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; } else { status = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetProtocol; } // bug fix : // don 't use the suggestion from smclib pSmartcardExtension->CardCapabilities.PtsData.Fl = pSmartcardExtension->CardCapabilities.Fl; pSmartcardExtension->CardCapabilities.PtsData.Dl = pSmartcardExtension->CardCapabilities.Dl; // CardMan 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) ); pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; } if (ulPtsType == PTS_TYPE_DEFAULT) { SmartcardDebug( DEBUG_PROTOCOL, ( "%s!overwriting PTS1 with default values\n", DRIVER_NAME) ); pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; } // set pts1 which codes Fl and Dl bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 | pSmartcardExtension->CardCapabilities.PtsData.Dl); SmartcardDebug( DEBUG_PROTOCOL, ( "%s!PTS1 = %x (suggestion)\n", DRIVER_NAME,bTemp) ); switch (bTemp) { case 0x11: // do nothing // we support these Fl/Dl parameters break; case 0x13: case 0x94: break ; case 0x14: // let's try it with 38400 baud SmartcardDebug( DEBUG_PROTOCOL, ( "%s!trying 57600 baud\n",DRIVER_NAME) ); // we must correct Fl/Dl pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x03; pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 | pSmartcardExtension->CardCapabilities.PtsData.Dl); break; default: SmartcardDebug( DEBUG_PROTOCOL, ( "%s!overwriting PTS1(0x%x)\n", DRIVER_NAME,bTemp) ); // we must correct Fl/Dl pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 | pSmartcardExtension->CardCapabilities.PtsData.Dl); break; } abPTSRequest[2] = bTemp; // set pck (check character) abPTSRequest[3] = (BYTE)(abPTSRequest[0] ^ abPTSRequest[1] ^ abPTSRequest[2]); SmartcardDebug(DEBUG_PROTOCOL,("%s!PTS request: 0x%x 0x%x 0x%x 0x%x\n", DRIVER_NAME, abPTSRequest[0], abPTSRequest[1], abPTSRequest[2], abPTSRequest[3])); MemSet(abPTSReply,sizeof(abPTSReply),0x00,sizeof(abPTSReply)); DebugStatus = SCCMN50M_EnterTransparentMode(pSmartcardExtension); // STEP 1 : write config + header to enter transparent mode SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, // Tx control 0, // Tx length 0, // Rx control 0); // Rx length status = SCCMN50M_WriteCardMan (pSmartcardExtension, 0, NULL); if (NT_ERROR(status)) { goto ExitSetProtocol; } pSmartcardExtension->ReaderExtension->fTransparentMode = TRUE; // if the inserted card uses inverse convention , we must now switch the COM port // to odd parity /* if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE) { pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = ODD_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { goto ExitTransparentTransmitT0; } } */ SmartcardDebug( DEBUG_PROTOCOL, ( "%s!writing PTS request\n", DRIVER_NAME) ); status = SCCMN50M_WriteCardMan(pSmartcardExtension, 4, abPTSRequest); if (status != STATUS_SUCCESS) { SmartcardDebug( DEBUG_PROTOCOL, ( "%s!writing PTS request failed\n", DRIVER_NAME) ); goto ExitSetProtocol; } // read back pts data SmartcardDebug( DEBUG_PROTOCOL, ( "%s!trying to read PTS reply\n", DRIVER_NAME) ); // first read CardMan header pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,3,&ulBytesRead,abReadBuffer,sizeof(abReadBuffer)); if (status != STATUS_SUCCESS && status != STATUS_IO_TIMEOUT ) { SmartcardDebug( DEBUG_PROTOCOL, ( "%s!reading status failed\n", DRIVER_NAME) ); goto ExitSetProtocol; } ulPTSReplyLength = 3; MemCpy(abPTSReply,sizeof(abPTSReply),abReadBuffer,3); // check if bit 5 is set if (abPTSReply[1] & 0x10) { pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,abReadBuffer,sizeof(abReadBuffer)); if (status != STATUS_SUCCESS && status != STATUS_IO_TIMEOUT ) { SmartcardDebug( DEBUG_PROTOCOL, ( "%s!reading status failed\n", DRIVER_NAME) ); goto ExitSetProtocol; } ulPTSReplyLength += 1; MemCpy(&abPTSReply[3],sizeof(abPTSReply)-3,abReadBuffer,1); } DebugStatus = SCCMN50M_ExitTransparentMode(pSmartcardExtension); pSmartcardExtension->ReaderExtension->fTransparentMode = FALSE; // to be sure that the new settings take effect pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250; DebugStatus = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; if (NT_SUCCESS(DebugStatus)) { DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulStatBytesRead,abStatReadBuffer,sizeof(abStatReadBuffer)); } #if DBG if (ulPTSReplyLength == 3) { SmartcardDebug(DEBUG_PROTOCOL,("PTS reply: 0x%x 0x%x 0x%x\n", abPTSReply[0], abPTSReply[1], abPTSReply[2])); } if (ulPTSReplyLength == 4) { SmartcardDebug(DEBUG_PROTOCOL,("PTS reply: 0x%x 0x%x 0x%x 0x%x\n", abPTSReply[0], abPTSReply[1], abPTSReply[2], abPTSReply[3])); } #endif if (ulPTSReplyLength == 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) ); break; } if (ulPTSReplyLength == 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) ); switch (bTemp) { case 0x11: break; case 0x13: SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ | ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ_FAST); break ; case 0x94: SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ | ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ_FAST); break; } break; } if (pSmartcardExtension->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 valies ulPtsType = pSmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT; pSmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; status = SCCMN50M_CardPower(pSmartcardExtension); continue; } // the card failed the pts request status = STATUS_DEVICE_PROTOCOL_ERROR; goto ExitSetProtocol; } ExitSetProtocol: switch (status) { case STATUS_IO_TIMEOUT: pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; *pSmartcardExtension->IoRequest.Information = 0; break; case STATUS_SUCCESS: // now indicate that we're in specific mode pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; // return the selected protocol to the caller *(PULONG) pSmartcardExtension->IoRequest.ReplyBuffer = pSmartcardExtension->CardCapabilities.Protocol.Selected; *pSmartcardExtension->IoRequest.Information = sizeof(pSmartcardExtension->CardCapabilities.Protocol.Selected); SmartcardDebug( DEBUG_PROTOCOL, ( "%s!Selected protocol: T=%ld\n", DRIVER_NAME,pSmartcardExtension->CardCapabilities.Protocol.Selected-1) ); break; default : pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; *pSmartcardExtension->IoRequest.Information = 0; break; } SmartcardDebug( DEBUG_TRACE, ( "%s!SetProtocol : Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: The smart card lib requires to have this function. It is called to setup event tracking for card insertion and removal events. Arguments: pSmartcardExtension - pointer to the smart card data struct. Return Value: NTSTATUS *****************************************************************************/ NTSTATUS SCCMN50M_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,SCCMN50M_Cancel); 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: *****************************************************************************/ VOID SCCMN50M_StopCardTracking( IN PDEVICE_EXTENSION pDeviceExtension ) { PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->SmartcardExtension; NTSTATUS status; SmartcardDebug( DEBUG_TRACE, ( "%s!StopCardTracking: Enter\n", DRIVER_NAME) ); if (pSmartcardExtension->ReaderExtension->ThreadObjectPointer != NULL) { // kill thread KeWaitForSingleObject(&pSmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL ); pSmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE; KeReleaseMutex(&pSmartcardExtension->ReaderExtension->CardManIOMutex,FALSE); // // Wait on the thread handle, when the wait is satisfied, the // thread has gone away. // status = KeWaitForSingleObject( pSmartcardExtension->ReaderExtension->ThreadObjectPointer, Executive, KernelMode, FALSE, NULL ); pSmartcardExtension->ReaderExtension->ThreadObjectPointer = NULL; } SmartcardDebug( DEBUG_TRACE, ( "%s!StopCardTracking: Exit %lx\n", DRIVER_NAME, status) ); } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_GetDeviceDescription (PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status; NTSTATUS DebugStatus; ULONG ulBytesRead; BYTE bByteRead; ULONG i,j; BYTE abReadBuffer[256]; ULONG ulPnPStringLength = 0; ULONG ulExtend; SmartcardDebug( DEBUG_TRACE, ( "%s!GetDeviceDescriptiong: Enter\n", DRIVER_NAME) ); // =============================== // clear any pending errors // =============================== status = SCCMN50M_GetCommStatus(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status)) goto ExitGetDeviceDescription; } // ================================= // set baudrate for CardMan to 1200 // ================================= pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 1200; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate, sizeof(SERIAL_BAUD_RATE)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status)) goto ExitGetDeviceDescription; } // =============================== // set comm timeouts // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = DEFAULT_READ_INTERVAL_TIMEOUT; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT + 5000; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutConstant = DEFAULT_WRITE_TOTAL_TIMEOUT_CONSTANT; pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutMultiplier = DEFAULT_WRITE_TOTAL_TIMEOUT_MULTIPLIER; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts, sizeof(SERIAL_TIMEOUTS)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_TIMEOUTS failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } // =============================== // set line control // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = NO_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 7; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } // =============================== // Set handflow // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XonLimit = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XoffLimit = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.FlowReplace = 0; pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.ControlHandShake = SERIAL_ERROR_ABORT | SERIAL_DTR_CONTROL; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_HANDFLOW; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow, sizeof(SERIAL_HANDFLOW)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_HANDFLOW); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_HANDFLOW failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } // =============================== // set purge mask // =============================== pSmartcardExtension->ReaderExtension->SerialConfigData.PurgeMask = SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT | SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR; // =============================== // clear RTS // =============================== status = SCCMN50M_ClearRTS(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } Wait(pSmartcardExtension,1); // =============================== // set DTR // =============================== status = SCCMN50M_SetDTR(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_DRT failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } Wait(pSmartcardExtension,1); // =============================== // set RTS // =============================== status = SCCMN50M_SetRTS(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } i=0; while (1) { pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,&bByteRead,sizeof(bByteRead)); if (status == STATUS_SUCCESS) { abReadBuffer[i++] = bByteRead; if (bByteRead == 0x29) { ulPnPStringLength = i; break; } } else { break; } } if (ulPnPStringLength > 11 ) { ulExtend = 0; for (i=0;iReaderExtension->abDeviceDescription[j] = abReadBuffer[i]; i++; j++; } SmartcardDebug( DEBUG_DRIVER, ( "%s!Device=%s\n", pSmartcardExtension->ReaderExtension->abDeviceDescription) ); break; } } } // =================== // restore baud rate // =================== pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate, sizeof(SERIAL_BAUD_RATE)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status)) goto ExitGetDeviceDescription; } // ==================== // retore line control // ==================== pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY; pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 8; pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer, &pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl, sizeof(SERIAL_LINE_CONTROL)); pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL); pSmartcardExtension->SmartcardReply.BufferLength = 0; status = SCCMN50M_SerialIo(pSmartcardExtension); if (!NT_SUCCESS(status)) { SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status)) goto ExitGetDeviceDescription; } ExitGetDeviceDescription: DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension); if (status != STATUS_SUCCESS) { // map all errors to STATUS_UNSUCCESSFULL; status = STATUS_UNSUCCESSFUL; } SmartcardDebug( DEBUG_TRACE, ( "%s!GetDeviceDescriptiong: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SetSyncParameters(IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status = STATUS_SUCCESS; SmartcardDebug( DEBUG_TRACE, ( "%s!SetSyncParameters: Enter\n", DRIVER_NAME) ); //DBGBreakPoint(); pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol = ((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulProtocol; pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileReading = ((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulStateResetLineWhileReading; pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileWriting = ((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulStateResetLineWhileWriting; pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks = ((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulWriteDummyClocks; pSmartcardExtension->ReaderExtension->SyncParameters.ulHeaderLen = ((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulHeaderLen; // Used for the 2 Wire Protocol. We must make a Card reset after Power On pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE; // return length of reply *pSmartcardExtension->IoRequest.Information = 0L; SmartcardDebug( DEBUG_TRACE, ( "%s!SetSyncParameters: Exit\n", DRIVER_NAME) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ UCHAR SCCMN50M_CalcTxControlByte (IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBitsToWrite ) { UCHAR bTxControlByte = 0; if (pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol == SCARD_PROTOCOL_2WBP) { bTxControlByte = CLOCK_FORCED_2WBP; } else { if (ulBitsToWrite >= 255 * 8) bTxControlByte |= TRANSMIT_A8; if (pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileWriting == SCARD_RESET_LINE_HIGH) bTxControlByte |= SYNC_RESET_LINE_HIGH; } bTxControlByte |= (BYTE)((ulBitsToWrite-1) & 0x00000007); return bTxControlByte; } //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ UCHAR SCCMN50M_CalcTxLengthByte (IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBitsToWrite ) { UCHAR bTxLengthByte = 0; bTxLengthByte = (BYTE)( ((ulBitsToWrite - 1) >> 3) + 1); return bTxLengthByte; } //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ UCHAR SCCMN50M_CalcRxControlByte (IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBitsToRead ) { UCHAR bRxControlByte = 0; if (pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileReading == SCARD_RESET_LINE_HIGH) bRxControlByte |= SYNC_RESET_LINE_HIGH; if (ulBitsToRead == 0) { ulBitsToRead = pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks; bRxControlByte |= SYNC_DUMMY_RECEIVE; } if (ulBitsToRead > 255 * 8) bRxControlByte |= RECEIVE_A8; bRxControlByte |= (BYTE)( (ulBitsToRead-1) & 0x00000007); return bRxControlByte; } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ UCHAR SCCMN50M_CalcRxLengthByte (IN PSMARTCARD_EXTENSION pSmartcardExtension, IN ULONG ulBitsToRead ) { UCHAR bRxLengthByte = 0; // if (pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol == SCARD_PROTOCOL_3WBP) // { if (ulBitsToRead == 0) ulBitsToRead = pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks; bRxLengthByte = (BYTE)( ((ulBitsToRead - 1) >> 3) + 1); // } return bRxLengthByte; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_SyncCardPowerOn ( IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH]; UCHAR abSyncAtrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength = 0; SmartcardDebug( DEBUG_TRACE, ( "%s!SyncCardPowerOn: Enter\n", DRIVER_NAME) ); status = SCCMN50M_UseSyncStrategy(pSmartcardExtension, &ulAtrLength, pbAtrBuffer, sizeof(pbAtrBuffer)); abSyncAtrBuffer[0] = 0x3B; abSyncAtrBuffer[1] = 0x04; MemCpy(&abSyncAtrBuffer[2], sizeof(abSyncAtrBuffer)-2, pbAtrBuffer, ulAtrLength); ulAtrLength += 2; MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer, sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer), abSyncAtrBuffer, ulAtrLength); pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)(ulAtrLength); pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE; pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested = FALSE; SmartcardDebug(DEBUG_ATR,("ATR of synchronous smart card : %2.2x %2.2x %2.2x %2.2x\n", pbAtrBuffer[0],pbAtrBuffer[1],pbAtrBuffer[2],pbAtrBuffer[3])); SmartcardDebug( DEBUG_TRACE, ( "%s!SyncCardPowerOn: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_Transmit2WBP(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; UCHAR bWriteBuffer [128]; UCHAR bReadBuffer [128]; UCHAR bTxControlByte; UCHAR bTxLengthByte; UCHAR bRxControlByte; UCHAR bRxLengthByte; ULONG ulBytesToWrite; ULONG ulBytesToRead; ULONG ulBitsToWrite; ULONG ulBitsToRead; ULONG ulBytesRead; // ULONG ulBitsRead; ULONG ulBytesStillToRead; ULONG ulMaxIFSD; PCHAR pbInData; SmartcardDebug( DEBUG_TRACE, ( "%s!Transmit2WBP: Enter\n", DRIVER_NAME) ); /*-----------------------------------------------------------------------*/ /** Power smartcard - if smartcard was removed and reinserted **/ /*-----------------------------------------------------------------------*/ if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested == TRUE) { status = SCCMN50M_SyncCardPowerOn (pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitTransmit2WBP; } } pbInData = pSmartcardExtension->IoRequest.RequestBuffer + sizeof(SYNC_TRANSFER); ulBitsToWrite = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToWrite; ulBitsToRead = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToRead; ulBytesToWrite = ulBitsToWrite/8; ulBytesToRead = ulBitsToRead/8 + (ulBitsToRead % 8 ? 1 : 0); /*-----------------------------------------------------------------------*/ // check buffer sizes /*-----------------------------------------------------------------------*/ ulMaxIFSD = ATTR_MAX_IFSD_CARDMAN_II; if (ulBytesToRead > ulMaxIFSD || ulBytesToRead > pSmartcardExtension->SmartcardReply.BufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitTransmit2WBP; } if (ulBytesToWrite > pSmartcardExtension->SmartcardRequest.BufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitTransmit2WBP; } pSmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWrite+1; /*-----------------------------------------------------------------------*/ // copy data to the Smartcard Request Buffer /*-----------------------------------------------------------------------*/ (pSmartcardExtension->SmartcardRequest.Buffer)[0] = '\x0F'; MemCpy((pSmartcardExtension->SmartcardRequest.Buffer+1), pSmartcardExtension->SmartcardRequest.BufferSize, pbInData, ulBytesToWrite); /*-----------------------------------------------------------------------*/ // copy data to the write buffer /*-----------------------------------------------------------------------*/ MemCpy((bWriteBuffer), sizeof(bWriteBuffer), pSmartcardExtension->SmartcardRequest.Buffer, (ulBytesToWrite+1)); /*-----------------------------------------------------------------------*/ // set SYNC protocol flag for CardMan /*-----------------------------------------------------------------------*/ SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN); /*-----------------------------------------------------------------------*/ // Header /*-----------------------------------------------------------------------*/ if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested == TRUE) { status = SCCMN50M_ResetCard2WBP(pSmartcardExtension); if (NT_ERROR(status)) { goto ExitTransmit2WBP; } pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = FALSE; } /*-----------------------------------------------------------------------*/ // 1. Send Carman-Header 4-Byte // 2. Send 0x0F, that builds a HIGH-LOW Edge for 4432 CC // 3. Send the Data (CC command = 3 Byte) /*-----------------------------------------------------------------------*/ bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension,ulBitsToWrite); bTxLengthByte = (BYTE)(SCCMN50M_CalcTxLengthByte(pSmartcardExtension,ulBitsToWrite)+1); bRxControlByte = 0; bRxLengthByte = 0; SCCMN50M_SetCardManHeader(pSmartcardExtension, bTxControlByte, bTxLengthByte, bRxControlByte, bRxLengthByte); /*-----------------------------------------------------------------------*/ // write data to card /*-----------------------------------------------------------------------*/ status = SCCMN50M_WriteCardMan (pSmartcardExtension, (ulBytesToWrite+1), bWriteBuffer); if (NT_ERROR(status)) { goto ExitTransmit2WBP; } /*-----------------------------------------------------------------------*/ // read CardMan Header // no Data from CC received /*-----------------------------------------------------------------------*/ pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension, 2, &ulBytesRead, bReadBuffer, sizeof(bReadBuffer)); if (NT_ERROR(status)) { goto ExitTransmit2WBP; } /*-----------------------------------------------------------------------*/ // 1. Send Carman-Header 4-Byte // 2. Send 0xF0, that builds a LOW-HIGH Edge for 4432 CC // 3. Now the receiviing of card-data begins /*-----------------------------------------------------------------------*/ bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension, 8); bTxLengthByte = SCCMN50M_CalcTxLengthByte(pSmartcardExtension, 8); bRxControlByte = SCCMN50M_CalcRxControlByte(pSmartcardExtension,ulBitsToRead); bRxLengthByte = SCCMN50M_CalcRxLengthByte(pSmartcardExtension,ulBitsToRead); SCCMN50M_SetCardManHeader(pSmartcardExtension, bTxControlByte, bTxLengthByte, bRxControlByte, bRxLengthByte); /*-----------------------------------------------------------------------*/ // in this sequnce SCCMN50M_WriteCardMan must not send the Config string. // write 0xF0 -> is the trigger to read data from card or start the // processing. /*-----------------------------------------------------------------------*/ pSmartcardExtension->ReaderExtension->NoConfig = TRUE; status = SCCMN50M_WriteCardMan (pSmartcardExtension, 1, // one byte to write "\xF0"); // LOW-HIGH - Edge if (NT_ERROR(status)) { goto ExitTransmit2WBP; } /*-----------------------------------------------------------------------*/ // read CardMan Header // Data from CC received will be received /*-----------------------------------------------------------------------*/ pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension, 2, &ulBytesRead, bReadBuffer, sizeof(bReadBuffer)); if (NT_ERROR(status)) { goto ExitTransmit2WBP; } /*-----------------------------------------------------------------------*/ // Read the data string /*-----------------------------------------------------------------------*/ ulBytesStillToRead = (ULONG)bReadBuffer[1]; if (bReadBuffer[0] & RECEIVE_A8) ulBytesStillToRead += 256; status = SCCMN50M_ReadCardMan(pSmartcardExtension, ulBytesStillToRead, &ulBytesRead, bReadBuffer, sizeof(bReadBuffer)); if (NT_ERROR(status)) { goto ExitTransmit2WBP; } /*-----------------------------------------------------------------------*/ /** calculate data length in bits - this value is not used **/ /*-----------------------------------------------------------------------*/ // ulBitsRead = ((ulBytesRead-1) * 8) + ((ulBitsToRead-1 ) & 0x00000007) + 1; /*-----------------------------------------------------------------------*/ /** shift the bits in the last byte to the correct position **/ /*-----------------------------------------------------------------------*/ bReadBuffer[ulBytesRead-1] >>= (7 - ((ulBitsToRead-1) & 0x00000007)); /*-----------------------------------------------------------------------*/ // the first bit of the returned string is lost // so we must shift the whole data string one bit left // the first bit of the first data byte is lost while reading // this bit maybe incorrect /*-----------------------------------------------------------------------*/ SCCMN50M_Shift_Msg(bReadBuffer, ulBytesRead); /*-----------------------------------------------------------------------*/ // copy received bytes to Smartcard Reply Buffer /*-----------------------------------------------------------------------*/ MemCpy(pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferSize, bReadBuffer, ulBytesRead); pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead; /*-----------------------------------------------------------------------*/ // copy received bytes to IoReply Buffer /*-----------------------------------------------------------------------*/ MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer, pSmartcardExtension->IoRequest.ReplyBufferLength, pSmartcardExtension->SmartcardReply.Buffer, ulBytesRead); *(pSmartcardExtension->IoRequest.Information) = ulBytesRead; ExitTransmit2WBP: SmartcardDebug( DEBUG_TRACE, ( "%s!Transmit2WBP: Exit\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ VOID SCCMN50M_Shift_Msg (PUCHAR pbBuffer, ULONG ulMsgLen) { UCHAR bTmp1, bTmp2; int i; for (i=(int)ulMsgLen-1; i>=0; i--) { bTmp1=(BYTE)((pbBuffer[i] >> 7) & 0x01); /* bTmp1 = bit 7 naechstes byte */ if (i+1 != (int)ulMsgLen) { bTmp2=(BYTE)((pbBuffer[i+1] << 1) | bTmp1); pbBuffer[i+1] = bTmp2; } } pbBuffer[0] = (BYTE)(pbBuffer[0] << 1); return; } /***************************************************************************** Routine Description: Reset Card 4442 Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_ResetCard2WBP(IN PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; BYTE bBuffer[10]; ULONG ulBytesRead; /*-----------------------------------------------------------------------*/ // Enter Card Reset /*-----------------------------------------------------------------------*/ SmartcardDebug( DEBUG_TRACE, ( "%s!ResetCard2WBP: Enter\n", DRIVER_NAME) ); /*-----------------------------------------------------------------------*/ // bTxControlByte = 0; // bTxLengthByte = 0; // bRxControlByte = RESET_CARD; // bRxLengthByte = 5; /*-----------------------------------------------------------------------*/ SCCMN50M_SetCardManHeader(pSmartcardExtension, 0, // bTxControlByte 0, // bTxLengthByte COLD_RESET, // bRxControlByte 5); // bRxLengthByte /*-----------------------------------------------------------------------*/ // write data to card /*-----------------------------------------------------------------------*/ status = SCCMN50M_WriteCardMan (pSmartcardExtension, 0, NULL); if (NT_ERROR(status)) { goto ExitResetCard2WBP; } /*-----------------------------------------------------------------------*/ // read CardMan Header /*-----------------------------------------------------------------------*/ pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension, 2, &ulBytesRead, bBuffer, sizeof(bBuffer)); if (NT_ERROR(status)) { goto ExitResetCard2WBP; } if (bBuffer[1] != 5) { status = !STATUS_SUCCESS; goto ExitResetCard2WBP; } /*-----------------------------------------------------------------------*/ // read ATR /*-----------------------------------------------------------------------*/ status = SCCMN50M_ReadCardMan(pSmartcardExtension, 5, &ulBytesRead, bBuffer, sizeof(bBuffer)); if (NT_ERROR(status)) { goto ExitResetCard2WBP; } SmartcardDebug(DEBUG_ATR,("%s!Card Reset ATR : %02x %02x %02x %02x\n", DRIVER_NAME,bBuffer[0],bBuffer[1],bBuffer[2],bBuffer[3])); ExitResetCard2WBP: SmartcardDebug( DEBUG_TRACE, ( "%s!ResetCard2WBP: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_Transmit3WBP(PSMARTCARD_EXTENSION pSmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; UCHAR bWriteBuffer [128]; UCHAR bReadBuffer [128]; UCHAR bTxControlByte; UCHAR bTxLengthByte; UCHAR bRxControlByte; UCHAR bRxLengthByte; ULONG ulBytesToWrite; ULONG ulBytesToRead; ULONG ulBitsToWrite; ULONG ulBitsToRead; ULONG ulBytesRead; // ULONG ulBitsRead; ULONG ulBytesStillToRead; ULONG ulMaxIFSD; PCHAR pbInData; SmartcardDebug( DEBUG_TRACE, ( "%s!Transmit3WBP: Enter\n", DRIVER_NAME) ); // DBGBreakPoint(); /*-----------------------------------------------------------------------*/ /** Power smartcard - if smartcard was removed and reinserted **/ /*-----------------------------------------------------------------------*/ if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested == TRUE) { status = SCCMN50M_SyncCardPowerOn (pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitTransmit3WBP; } } pbInData = pSmartcardExtension->IoRequest.RequestBuffer + sizeof(SYNC_TRANSFER); ulBitsToWrite = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToWrite; ulBitsToRead = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToRead; ulBytesToWrite = ulBitsToWrite/8; ulBytesToRead = ulBitsToRead/8 + (ulBitsToRead % 8 ? 1 : 0); /*-----------------------------------------------------------------------*/ // check buffer sizes /*-----------------------------------------------------------------------*/ ulMaxIFSD = ATTR_MAX_IFSD_CARDMAN_II; if (ulBytesToRead > ulMaxIFSD || ulBytesToRead > pSmartcardExtension->SmartcardReply.BufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitTransmit3WBP; } if (ulBytesToWrite > pSmartcardExtension->SmartcardRequest.BufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitTransmit3WBP; } pSmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWrite; /*-----------------------------------------------------------------------*/ // copy data to the Smartcard Request Buffer /*-----------------------------------------------------------------------*/ MemCpy(pSmartcardExtension->SmartcardRequest.Buffer, pSmartcardExtension->SmartcardRequest.BufferSize, pbInData, ulBytesToWrite); /*-----------------------------------------------------------------------*/ // copy data to the write buffer /*-----------------------------------------------------------------------*/ MemCpy(bWriteBuffer, sizeof(bWriteBuffer), pSmartcardExtension->SmartcardRequest.Buffer, ulBytesToWrite); /*-----------------------------------------------------------------------*/ // set SYNC protocol flag for CardMan /*-----------------------------------------------------------------------*/ SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN); /*-----------------------------------------------------------------------*/ // build cardman header /*-----------------------------------------------------------------------*/ bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension,ulBitsToWrite); bTxLengthByte = SCCMN50M_CalcTxLengthByte(pSmartcardExtension,ulBitsToWrite); bRxControlByte = SCCMN50M_CalcRxControlByte(pSmartcardExtension,ulBitsToRead); bRxLengthByte = SCCMN50M_CalcRxLengthByte(pSmartcardExtension,ulBitsToRead); SCCMN50M_SetCardManHeader(pSmartcardExtension, bTxControlByte, bTxLengthByte, bRxControlByte, bRxLengthByte); /*-----------------------------------------------------------------------*/ /** write data to card **/ /*-----------------------------------------------------------------------*/ status = SCCMN50M_WriteCardMan (pSmartcardExtension, ulBytesToWrite, bWriteBuffer); if (NT_ERROR(status)) { goto ExitTransmit3WBP; } /*-----------------------------------------------------------------------*/ /** read CardMan Header **/ /*-----------------------------------------------------------------------*/ pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (NT_ERROR(status)) { goto ExitTransmit3WBP; } /*-----------------------------------------------------------------------*/ // calc data length to receive /*-----------------------------------------------------------------------*/ ulBytesStillToRead = (ULONG)(bReadBuffer[1]); if (bReadBuffer[0] & RECEIVE_A8) ulBytesStillToRead += 256; // read data from card status = SCCMN50M_ReadCardMan(pSmartcardExtension, ulBytesStillToRead, &ulBytesRead, bReadBuffer, sizeof(bReadBuffer)); if (NT_ERROR(status)) { goto ExitTransmit3WBP; } /*-----------------------------------------------------------------------*/ // calculate data length in bits - this value is not used /*-----------------------------------------------------------------------*/ // ulBitsRead = ((ulBytesRead-1) * 8) + ((ulBitsToRead-1 ) & 0x00000007) + 1; /*-----------------------------------------------------------------------*/ // shift the bits in the last byte to the correct position /*-----------------------------------------------------------------------*/ bReadBuffer[ulBytesRead-1] >>= (7 - ((ulBitsToRead-1) & 0x00000007)); /*-----------------------------------------------------------------------*/ // copy received bytes to Smartcard Reply Buffer /*-----------------------------------------------------------------------*/ MemCpy(pSmartcardExtension->SmartcardReply.Buffer, pSmartcardExtension->SmartcardReply.BufferSize, bReadBuffer, ulBytesRead); pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead; /*-----------------------------------------------------------------------*/ // copy received bytes to IoReply Buffer // this Memcpy should respond to SmartcardRawReply function /*-----------------------------------------------------------------------*/ MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer, pSmartcardExtension->IoRequest.ReplyBufferLength, pSmartcardExtension->SmartcardReply.Buffer, ulBytesRead); *pSmartcardExtension->IoRequest.Information = ulBytesRead; ExitTransmit3WBP: SmartcardDebug( DEBUG_TRACE, ( "%s!Transmit3WBP: Exit %lx\n", DRIVER_NAME,status) ); return status; } /***************************************************************************** Routine Description: This function powers a synchronous smart card. Arguments: Return Value: *****************************************************************************/ NTSTATUS SCCMN50M_UseSyncStrategy ( IN PSMARTCARD_EXTENSION pSmartcardExtension, OUT PULONG pulAtrLength, OUT PUCHAR pbAtrBuffer, IN ULONG ulAtrBufferSize ) { NTSTATUS status; NTSTATUS DebugStatus; UCHAR bReadBuffer[SCARD_ATR_LENGTH]; ULONG ulBytesRead; SmartcardDebug( DEBUG_TRACE, ( "%s!UseSyncStrategy: Enter\n", DRIVER_NAME) ); //DBGBreakPoint(); SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,SYNC_ATR_RX_CONTROL,ATR_LEN_SYNC); pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = SYNC_RESET_DELAY; pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02; SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS); SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY ); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN); status = SCCMN50M_ResyncCardManII(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitPowerSynchronousCard; } // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitPowerSynchronousCard; } pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; // read state and length status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); if (status != STATUS_SUCCESS) { goto ExitPowerSynchronousCard; } if (bReadBuffer[1] < MIN_ATR_LEN ) { // read all remaining bytes from the CardMan DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer)); status = STATUS_UNRECOGNIZED_MEDIA; goto ExitPowerSynchronousCard; } if (bReadBuffer[1] > ulAtrBufferSize) { status = STATUS_BUFFER_OVERFLOW; goto ExitPowerSynchronousCard; } // read ATR status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],pulAtrLength,pbAtrBuffer,ulAtrBufferSize); if (status != STATUS_SUCCESS) { goto ExitPowerSynchronousCard; } if (pbAtrBuffer[0] == 0x00 || pbAtrBuffer[0] == 0xff ) { status = STATUS_UNRECOGNIZED_MEDIA; goto ExitPowerSynchronousCard; } pSmartcardExtension->ReaderExtension->fRawModeNecessary = TRUE; ExitPowerSynchronousCard: SmartcardDebug( DEBUG_TRACE, ( "%s!UseSyncStrategy: Exit %lx\n", DRIVER_NAME,status) ); SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,IGNORE_PARITY | CM2_GET_ATR); SCCMN50M_ClearCardManHeader(pSmartcardExtension); return status; } /***************************************************************************** Routine Description: This function checks if the inserted card is a synchronous one Arguments: Return Value: *****************************************************************************/ BOOLEAN SCCMN50M_IsAsynchronousSmartCard( IN PSMARTCARD_EXTENSION pSmartcardExtension ) { NTSTATUS status; UCHAR ReadBuffer[3]; ULONG ulBytesRead; BOOLEAN fIsAsynchronousSmartCard = TRUE; UCHAR abATR[33]; SmartcardDebug( DEBUG_TRACE, ( "%s!IsAsynchronousSmartcard: Enter \n", DRIVER_NAME) ); pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 200; // 3MHz smart card ? SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,1); SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS); SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ); // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitIsAsynchronousSmartCard; } pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; // read state and length status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); if (status == STATUS_SUCCESS && ReadBuffer[1] == 0x01 ) { goto ExitIsAsynchronousSmartCard; } // --------------------------------------- // power off card // --------------------------------------- status = SCCMN50M_PowerOff(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitIsAsynchronousSmartCard; } // 5MHz smart card ? SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,1); SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS); SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR); SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ); // write config + header status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL); if (status != STATUS_SUCCESS) { goto ExitIsAsynchronousSmartCard; } pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE; // read state and length status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer)); if (status == STATUS_SUCCESS && ReadBuffer[1] == 0x01 ) { goto ExitIsAsynchronousSmartCard; } // now we assume that it is a synchronous smart card fIsAsynchronousSmartCard = FALSE; // --------------------------------------- // power off card // --------------------------------------- status = SCCMN50M_PowerOff(pSmartcardExtension); if (status != STATUS_SUCCESS) { goto ExitIsAsynchronousSmartCard; } ExitIsAsynchronousSmartCard: pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT; SmartcardDebug( DEBUG_TRACE, ( "%s!IsAsynchronousSmartcard: Exit \n", DRIVER_NAME) ); return fIsAsynchronousSmartCard; } /***************************************************************************** * History: * $Log: sccmcb.c $ * Revision 1.7 2001/01/22 08:39:41 WFrischauf * No comment given * * Revision 1.6 2000/09/25 10:46:22 WFrischauf * No comment given * * Revision 1.5 2000/08/24 09:05:44 TBruendl * No comment given * * Revision 1.4 2000/08/16 08:24:04 TBruendl * warning :uninitialized memory removed * * Revision 1.3 2000/07/28 09:24:12 TBruendl * Changes for OMNIKEY on Whistler CD * * Revision 1.16 2000/06/27 11:56:28 TBruendl * workaraound for SAMOR smart cards with invalid ATR (ITSEC) * * Revision 1.15 2000/06/08 10:08:47 TBruendl * bug fix : warm reset for ScfW * * Revision 1.14 2000/05/23 09:58:26 TBruendl * OMNIKEY 3.0.0.1 * * Revision 1.13 2000/04/13 08:07:22 TBruendl * PPS bug fix for SCfW * * Revision 1.12 2000/04/04 07:52:18 TBruendl * problem with the new WfsC fixed * * Revision 1.11 2000/03/03 09:50:50 TBruendl * No comment given * * Revision 1.10 2000/03/01 09:32:04 TBruendl * R02.20.0 * * Revision 1.9 2000/01/04 10:40:33 TBruendl * bug fix: status instead of DebugStatus used * * Revision 1.8 1999/12/16 14:10:16 TBruendl * After transparent mode has been left, the status is read from the CardMan to be sure that * the new settings are effective. * * Revision 1.6 1999/12/13 07:55:38 TBruendl * Bug fix for P+ druing initialization * PTS for 4.9 mhz smartcards added * * Revision 1.5 1999/11/04 07:53:21 WFrischauf * bug fixes due to error reports 2 - 7 * * Revision 1.4 1999/07/12 12:49:04 TBruendl * Bug fix: Resync after GET_DEVICE_DESCRIPTION * Power On SLE4428 * * Revision 1.3 1999/06/10 09:03:57 TBruendl * No comment given * * Revision 1.2 1999/02/25 10:12:22 TBruendl * No comment given * * Revision 1.1 1999/02/02 13:34:37 TBruendl * This is the first release (R01.00) of the IFD handler for CardMan running under NT5.0. * * *****************************************************************************/