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

📄 tlp3cb.c

📁 SmardCard Windows驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	PULONG serialIoControlCode = &SmartcardExtension->ReaderExtension->SerialIoControlCode;
	ULONG bytesToSend, bytesToRead, currentByte = 0;
    BOOLEAN restartWorkWaitingTime = FALSE;
	NTSTATUS status;

    PAGED_CODE();

    SmartcardDebug(
        DEBUG_TRACE,
        ("%s!TLP3TransmitT0: Enter\n",
        DRIVER_NAME)
        );

    try {
	
	    // Let the lib build a T=0 packet
	    status = SmartcardT0Request(SmartcardExtension);

	    if (status != STATUS_SUCCESS) 
            leave;

	    //
	    // The number of bytes we expect from the card
	    // is Le + 2 status bytes
	    //
	    bytesToSend = *requestLength;
	    bytesToRead = SmartcardExtension->T0.Le + 2;

	    //
	    // Send the first 5 bytes to the card
	    //
	    *requestLength = 5;

	    do {

    	    UCHAR procByte;

            //
            // According to ISO 7816 a procedure byte of 
            // 60 should be treated as a request for a one time wait.
            // In this case we do not write anything to the card
            //
            if (restartWorkWaitingTime == FALSE) {

                SmartcardDebug(
                    DEBUG_PROTOCOL,
                    ("%s!TLP3TransmitT0: -> Sending %s (%ld bytes)\n",
                    DRIVER_NAME,
                    (currentByte == 0 ? "header" : "data"),
                    *requestLength)
                    );
		        //
		        // Write to the card
		        //
		        *serialIoControlCode = SMARTCARD_WRITE;
		        SmartcardExtension->SmartcardRequest.Buffer = &requestBuffer[currentByte];

		        status = TLP3SerialIo(SmartcardExtension);

		        if (status != STATUS_SUCCESS) {
                 	
                    SmartcardDebug(
                        DEBUG_ERROR,
                        ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_WRITE) returned %lx\n",
                        DRIVER_NAME,
                        status)
                        );
                 	
                    leave;
                }

		        //
		        // The TLP3 echos all sent bytes. We read the echo 
		        // back into our send buffer
		        //
		        *serialIoControlCode = SMARTCARD_READ;
		        *replyLength = *requestLength;
		        SmartcardExtension->SmartcardReply.Buffer = &requestBuffer[currentByte];
                                                    
		        status = TLP3SerialIo(SmartcardExtension);

		        if (status != STATUS_SUCCESS) {
                 	
                    SmartcardDebug(
                        DEBUG_ERROR,
                        ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_READ) returned %lx\n",
                        DRIVER_NAME,
                        status)
                        );

                    leave;
                }

		        currentByte += *requestLength;
		        bytesToSend -= *requestLength;
            }

		    // Read the 'Procedure byte'.
		    SmartcardExtension->SmartcardReply.Buffer = &procByte;
		    *serialIoControlCode = SMARTCARD_READ;
		    *replyLength = 1;

		    status = TLP3SerialIo(SmartcardExtension);

		    if (status != STATUS_SUCCESS) {
             	
                SmartcardDebug(
                    DEBUG_ERROR,
                    ("%s!TLP3TransmitT0: TLP3SerialIo(SMARTCARD_READ) returned %lx\n",
                    DRIVER_NAME,
                    status)
                    );

                leave;
            }

            restartWorkWaitingTime = FALSE;
		    //
		    // Check the procedure byte. 
		    // Please take a look at ISO 7816 Part 3 Section 8.2.2
		    //
		    if (procByte == requestBuffer[1] || 
			    procByte == requestBuffer[1] + 1) {

                SmartcardDebug(
                    DEBUG_PROTOCOL,
                    ("%s!TLP3TransmitT0: <- ACK (send all)\n",
                    DRIVER_NAME)
                    );

			    // All remaining data bytes can be sent at once
			    *requestLength = bytesToSend;

		    } else if (procByte == (UCHAR) ~requestBuffer[1] ||
				       procByte == (UCHAR) ~(requestBuffer[1] + 1)) {

                SmartcardDebug(
                    DEBUG_PROTOCOL,
                    ("%s!TLP3TransmitT0: <- ACK (send single)\n",
                    DRIVER_NAME)
                    );

			    // We can send only one byte
			    *requestLength = 1;

		    } else if (procByte == 0x60 ||
                       SmartcardExtension->CardCapabilities.InversConvention &&
                       procByte == 0xf9) {

                //
                // We have to reset the wait time and try again to read
                //
                ULONG TimeRes;
			    LARGE_INTEGER delayTime;

                SmartcardDebug(
                    DEBUG_PROTOCOL,
                    ("%s!TLP3TransmitT0: <- NULL (%ldms)\n",
                    DRIVER_NAME,
                    SmartcardExtension->CardCapabilities.T0.WT / 1000)
                    );

                TimeRes = KeQueryTimeIncrement();

			    delayTime.HighPart = -1;
			    delayTime.LowPart = 
                    (-1) * 
                    TimeRes * 
                    ((SmartcardExtension->CardCapabilities.T0.WT * 10l / TimeRes) + 1); 

			    KeDelayExecutionThread(
				    KernelMode,
				    FALSE,
				    &delayTime
				    );

                //
                // Set flag that we only should read the proc byte
                // without writing data to the card
                //
                restartWorkWaitingTime = TRUE;

            } else {
         	    
			    //
			    // The card returned a status byte.
			    // Status bytes are always two bytes long.
			    // Store this byte first and then read the next
			    //
			    replyBuffer[0] = procByte;

			    *serialIoControlCode = SMARTCARD_READ;
			    *replyLength = 1;
			    bytesToSend = 0;
			    bytesToRead = 0;

			    //
			    // Read in the second status byte
			    //
			    SmartcardExtension->SmartcardReply.Buffer = 
				    &replyBuffer[1];

			    status = TLP3SerialIo(SmartcardExtension);

			    SmartcardExtension->SmartcardReply.BufferLength = 2;

                SmartcardDebug(
                    (status == STATUS_SUCCESS ? DEBUG_PROTOCOL : DEBUG_ERROR),
                    ("%s!TLP3TransmitT0: <- SW1=%02x SW2=%02x (%lx)\n",
                    DRIVER_NAME,
                    replyBuffer[0], 
                    replyBuffer[1],
                    status)
                    );
		    }

	    } while(bytesToSend || restartWorkWaitingTime);

	    if (status != STATUS_SUCCESS)
		    leave;

	    if (bytesToRead != 0) {

		    *serialIoControlCode = SMARTCARD_READ;
		    *replyLength = bytesToRead;

	        SmartcardExtension->SmartcardReply.Buffer = 
		        replyBuffer;

		    status = TLP3SerialIo(SmartcardExtension);

            SmartcardDebug(
                (status == STATUS_SUCCESS ? DEBUG_PROTOCOL : DEBUG_ERROR),
                ("%s!TLP3TransmitT0: <- Data %ld bytes, SW1=%02x SW2=%02x (%lx)\n",
                DRIVER_NAME,
                bytesToRead,
                replyBuffer[bytesToRead - 2], 
                replyBuffer[bytesToRead - 1],
                status)
                );
	    }
    }
    finally {

	    // Restore pointers to their original location
	    SmartcardExtension->SmartcardRequest.Buffer = 
		    requestBuffer;

	    SmartcardExtension->SmartcardReply.Buffer = 
		    replyBuffer;

        if (status == STATUS_TIMEOUT) {

            // STATUS_TIMEOUT is not mapped to a Win32 error code
            status = STATUS_IO_TIMEOUT;         	
        }

        if (status == STATUS_SUCCESS) {
         	
	        status = SmartcardT0Reply(SmartcardExtension);
        }
    }

    SmartcardDebug(
        (status == STATUS_SUCCESS ? DEBUG_TRACE : DEBUG_ERROR),
        ("%s!TLP3TransmitT0: Exit(%lx)\n",
        DRIVER_NAME,
        status)
        );

	return status;
}	

NTSTATUS
TLP3Transmit(
	PSMARTCARD_EXTENSION SmartcardExtension
	)
/*++

Routine Description:

	This function is called by the smart card library whenever a transmission
	is required. 

Arguments:

    SmartcardExtension - Pointer to smart card data struct.

Return Value:

    NTSTATUS

--*/
{
	NTSTATUS status;

    PAGED_CODE();

    SmartcardDebug(
        DEBUG_TRACE,
        ("%s!TLP3Transmit: Enter\n",
        DRIVER_NAME)
        );

    _try {
     	
	    do {

		    PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
		    PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
		    PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
		    PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
		    PULONG serialIoControlCode = &SmartcardExtension->ReaderExtension->SerialIoControlCode;

		    //
		    // Tell the lib function how many bytes I need for the prologue
		    //
		    *requestLength = 0;

		    switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {

			    case SCARD_PROTOCOL_RAW:
				    status = SmartcardRawRequest(SmartcardExtension);
				    break;

			    case SCARD_PROTOCOL_T0:
				    //
				    // T=0 requires a bit more work.
				    // So we do this in a seperate function.
				    //
				    status = TLP3TransmitT0(SmartcardExtension);
                    leave;
				    
			    case SCARD_PROTOCOL_T1:
				    status = SmartcardT1Request(SmartcardExtension);
				    break;

			    default:
				    status = STATUS_INVALID_DEVICE_REQUEST;
                    leave;
				    
		    }

		    if (status != STATUS_SUCCESS) {

			    leave;
		    }

		    //
		    // Write the command to the card
		    //
		    *replyLength = 0;
		    *serialIoControlCode = SMARTCARD_WRITE;

		    status = TLP3SerialIo(SmartcardExtension);

		    if (status != STATUS_SUCCESS) {

			    leave;
		    }

		    //
		    // The Bull reader always echos the bytes sent, so read that echo back
		    //
		    *serialIoControlCode = SMARTCARD_READ;
		    *replyLength = *requestLength;

		    status = TLP3SerialIo(SmartcardExtension);

		    if (status != STATUS_SUCCESS) {

			    leave;
		    }

		    switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {

			    case SCARD_PROTOCOL_RAW:
				    status = SmartcardRawReply(SmartcardExtension);
				    break;

			    case SCARD_PROTOCOL_T1:
                    //
                    // Check if the card requested a waiting time extension
                    //
                    if (SmartcardExtension->T1.Wtx) {

                        LARGE_INTEGER waitTime;
     	  	            waitTime.HighPart = -1;
			            waitTime.LowPart = 
                            SmartcardExtension->T1.Wtx * 
                            SmartcardExtension->CardCapabilities.T1.BWT * 
                            (-10);

                        KeDelayExecutionThread(
                            KernelMode,
                            FALSE,
                            &waitTime
                            );
                    }

				    //
				    // Read NAD, PCB and LEN fields
				    //
				    *replyLength = 3;

				    status = TLP3SerialIo(SmartcardExtension);

                    // 
                    // Check for timeout first. If the card did not reply 
                    // we need to send a resend request
                    //
                    if (status != STATUS_TIMEOUT) {

				        if (status != STATUS_SUCCESS) {

					        leave;
				        }

				        //
				        // The third byte contains the length of the data in the packet
				        // and we additinally want to have the EDC bytes which 
				        // is one for LRC and 2 for CRC
				        //
				        *replyLength = 
					        replyBuffer[2] + 

⌨️ 快捷键说明

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