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

📄 tlp3nt.c

📁 bull tlp3智能卡读卡器的驱动程序示例
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (C) 1997, 98 Microsoft Corporation

Module Name:

    bulltlp3.c

Abstract:

    Smart card driver for Bull TLP3 reader

Author:

    Klaus U. Schutz
                                  
Environment:

    Kernel mode                        

Revision History :

    Nov. 1997 - 1.0 Release
    Jan. 1998 - Fix for vendor defined IOCTLs
                TLP3SerialIo now writes the whole data packet if GT is 0
                Support for higher data rates added
    Feb. 1998 - PnP version

--*/
                                            
#include <stdio.h> 
#include "bulltlp3.h"

#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGEABLE, TLP3CreateAndStartDevice)
#pragma alloc_text(PAGEABLE, TLP3StartSerialEventTracking)
#pragma alloc_text(PAGEABLE, TLP3AddDevice)
#pragma alloc_text(PAGEABLE, TLP3CreateDevice)
#pragma alloc_text(PAGEABLE, TLP3RemoveDevice)
#pragma alloc_text(PAGEABLE, TLP3DriverUnload)

#if DBG
#pragma optimize ("", off)
#endif

#ifdef SIMULATION
PWSTR DriverKey;
#endif

NTSTATUS
DriverEntry(
    IN  PDRIVER_OBJECT  DriverObject,   
    IN  PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    This routine is called at system initialization time to initialize
    this driver.

Arguments:

    DriverObject    - Supplies the driver object.
    RegistryPath    - Supplies the registry path for this driver.

Return Value:

    STATUS_SUCCESS          - We could initialize at least one device.
    STATUS_NO_SUCH_DEVICE   - We could not initialize even one device.

--*/
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG device;

    SmartcardDebug(
        DEBUG_INFO,
	    ("%s!DriverEntry: Enter - %s %s\n", 
        DRIVER_NAME,                                 
        __DATE__,
        __TIME__)
        )

    //
    // we do some stuff in this driver that 
    // assumes a single digit port number
    //
    ASSERT(MAXIMUM_SERIAL_READERS < 10);

    // Initialize the Driver Object with driver's entry points
    DriverObject->DriverUnload = TLP3DriverUnload;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = TLP3CreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = TLP3CreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TLP3Cleanup;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TLP3DeviceControl;
	DriverObject->MajorFunction[IRP_MJ_PNP]	= TLP3PnP;
	DriverObject->MajorFunction[IRP_MJ_POWER] = TLP3Power;
    DriverObject->DriverExtension->AddDevice = TLP3AddDevice;

#ifdef SIMULATION
	DriverKey = ExAllocatePool(PagedPool, RegistryPath->Length + sizeof(L""));

	if (DriverKey) {

		RtlZeroMemory(
			DriverKey,
			RegistryPath->Length + sizeof(L"")
			);

		RtlCopyMemory(
			DriverKey,
			RegistryPath->Buffer,
			RegistryPath->Length
			);
	}
#endif

    return status;
}

NTSTATUS
TLP3AddDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++

Routine Description:

    This routine creates an object for the physical device specified and
    sets up the deviceExtension.

--*/
{
    PDEVICE_EXTENSION deviceExtension;
	NTSTATUS status = STATUS_SUCCESS;
	PREADER_EXTENSION readerExtension;
    PSMARTCARD_EXTENSION smartcardExtension;
	ULONG deviceInstance;
	HANDLE regKey = NULL;
	PDEVICE_OBJECT DeviceObject = NULL;

    // this is a list of our supported data rates
    static ULONG dataRatesSupported[] = { 9600, 19200, 38400, 57600, 115200 };


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

    PAGED_CODE();

	__try {

		// Create the device object
		status = IoCreateDevice(
			DriverObject,
			sizeof(DEVICE_EXTENSION),
			NULL,
			FILE_DEVICE_SMARTCARD,
			0,
			TRUE,
			&DeviceObject
			);

		if (status != STATUS_SUCCESS) {

			SmartcardLogError(
				DriverObject,
				TLP3_CANT_CREATE_DEVICE,
				NULL,
				0
				);

			__leave;
		}

		SmartcardDebug( 
			DEBUG_TRACE, 
			( "%s!TLP3CreateDevice: Device created\n",
			DRIVER_NAME)
			);

		//	set up the device extension.
		deviceExtension = DeviceObject->DeviceExtension;
		smartcardExtension = &deviceExtension->SmartcardExtension;

		deviceExtension->CloseSerial = IoAllocateWorkItem(
			DeviceObject
			);

		// Used for stop / start notification
		KeInitializeEvent(
			&deviceExtension->ReaderStarted,
			NotificationEvent,
			FALSE
			);   

		// Used to keep track of open close calls
		deviceExtension->ReaderOpen = FALSE;

		KeInitializeSpinLock(&deviceExtension->SpinLock);

		// Allocate data struct space for smart card reader
		smartcardExtension->ReaderExtension = ExAllocatePool(
			NonPagedPool,
			sizeof(READER_EXTENSION)
			);

		if (smartcardExtension->ReaderExtension == NULL) {

			SmartcardLogError(
				DriverObject,
				TLP3_NO_MEMORY,
				NULL,
				0
				);

			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		readerExtension = smartcardExtension->ReaderExtension;
		RtlZeroMemory(readerExtension, sizeof(READER_EXTENSION));

		// Write the version of the lib we use to the smartcard extension
		smartcardExtension->Version = SMCLIB_VERSION;
		smartcardExtension->SmartcardRequest.BufferSize = 
		smartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;

		//
		// Now let the lib allocate the buffer for data transmission
		// We can either tell the lib how big the buffer should be
		// by assigning a value to BufferSize or let the lib
		// allocate the default size
		//
		status = SmartcardInitialize(smartcardExtension);

		if (status != STATUS_SUCCESS) {

			SmartcardLogError(
				DriverObject,
				(smartcardExtension->OsData ? TLP3_WRONG_LIB_VERSION : TLP3_NO_MEMORY),
				NULL,
				0
				);

			__leave;
		}

		// Save deviceObject
		smartcardExtension->OsData->DeviceObject = DeviceObject;

		// Set up call back functions 
		smartcardExtension->ReaderFunction[RDF_TRANSMIT] = TLP3Transmit;
		smartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = TLP3SetProtocol;
		smartcardExtension->ReaderFunction[RDF_CARD_POWER] = TLP3ReaderPower;
		smartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = TLP3CardTracking;
		smartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = TLP3VendorIoctl;

		// This event signals that the serial driver has been closed
		KeInitializeEvent(
			&READER_EXTENSION_L(SerialCloseDone),
			NotificationEvent,
			TRUE
			); 

		//
		// Set the vendor information
		//
		strcpy(smartcardExtension->VendorAttr.VendorName.Buffer, "Bull");

		smartcardExtension->VendorAttr.VendorName.Length = 
			strlen(deviceExtension->SmartcardExtension.VendorAttr.VendorName.Buffer);

		strcpy(smartcardExtension->VendorAttr.IfdType.Buffer, "SmarTLP");

		smartcardExtension->VendorAttr.IfdType.Length = 
			strlen(smartcardExtension->VendorAttr.IfdType.Buffer);

 		smartcardExtension->VendorAttr.UnitNo = MAXULONG;

		for (deviceInstance = 0; deviceInstance < MAXULONG; deviceInstance++) {

			PDEVICE_OBJECT devObj;

			for (devObj = DeviceObject; 
				 devObj != NULL; 
				 devObj = devObj->NextDevice) {

				 PDEVICE_EXTENSION devExt = devObj->DeviceExtension;
				 PSMARTCARD_EXTENSION smcExt = &devExt->SmartcardExtension;

				 if (deviceInstance == smcExt->VendorAttr.UnitNo) {

					 break;
				 }
			}
			if (devObj == NULL) {

				smartcardExtension->VendorAttr.UnitNo = deviceInstance;
				break;
			}
		}

		//
		// Set the reader capabilities
		//

		// Clk frequency in KHz encoded as little endian integer
		smartcardExtension->ReaderCapabilities.CLKFrequency.Default = 3571;
		smartcardExtension->ReaderCapabilities.CLKFrequency.Max = 3571;

		smartcardExtension->ReaderCapabilities.DataRate.Default = 
		smartcardExtension->ReaderCapabilities.DataRate.Max = 
			dataRatesSupported[0];

		// reader could support higher data rates
		smartcardExtension->ReaderCapabilities.DataRatesSupported.List = 
			dataRatesSupported;
		smartcardExtension->ReaderCapabilities.DataRatesSupported.Entries = 
			sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]);

		smartcardExtension->ReaderCapabilities.MaxIFSD = 254;

		// Now setup information in our deviceExtension
		smartcardExtension->ReaderCapabilities.CurrentState = 
			(ULONG) SCARD_UNKNOWN;

		// This reader supports T=0 and T=1
		smartcardExtension->ReaderCapabilities.SupportedProtocols = 
			SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;

		smartcardExtension->ReaderCapabilities.MechProperties = 0;

		//
		// Set serial configuration parameters
		//
		readerExtension->SerialConfigData.BaudRate.BaudRate = 9600;

		readerExtension->SerialConfigData.LineControl.StopBits = 
			STOP_BITS_2;
		readerExtension->SerialConfigData.LineControl.Parity = 
			EVEN_PARITY;
		readerExtension->SerialConfigData.LineControl.WordLength = 
			SERIAL_DATABITS_8;

		// set timeouts
		readerExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = 
			READ_INTERVAL_TIMEOUT_DEFAULT;
		readerExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 
			READ_TOTAL_TIMEOUT_CONSTANT_DEFAULT;
		readerExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 0;

		// set special characters
		readerExtension->SerialConfigData.SerialChars.ErrorChar = 0;
		readerExtension->SerialConfigData.SerialChars.EofChar = 0;
		readerExtension->SerialConfigData.SerialChars.EventChar = 0;
		readerExtension->SerialConfigData.SerialChars.XonChar = 0;
		readerExtension->SerialConfigData.SerialChars.XoffChar = 0;
		readerExtension->SerialConfigData.SerialChars.BreakChar = 0xFF;

		// Set handflow
		readerExtension->SerialConfigData.HandFlow.XonLimit = 0;
		readerExtension->SerialConfigData.HandFlow.XoffLimit = 0;
		readerExtension->SerialConfigData.HandFlow.ControlHandShake = 0;
		readerExtension->SerialConfigData.HandFlow.FlowReplace = 
			SERIAL_XOFF_CONTINUE;
#if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
		readerExtension->SerialConfigData.HandFlow.ControlHandShake = 
			SERIAL_ERROR_ABORT;
#endif

		// save the current power state of the reader
		readerExtension->ReaderPowerState = PowerReaderWorking;

        // and attach to the PDO
		ATTACHED_DEVICE_OBJECT = 
            IoAttachDeviceToDeviceStack(
            DeviceObject, 
            PhysicalDeviceObject
            );

        ASSERT(ATTACHED_DEVICE_OBJECT != NULL);

        if (ATTACHED_DEVICE_OBJECT == NULL) {

	        SmartcardLogError(
		        DriverObject,
		        TLP3_CANT_CONNECT_TO_ASSIGNED_PORT,
		        NULL,
		        status
		        );

            status = STATUS_UNSUCCESSFUL;
            __leave;
        }

        // register our new device
        status = IoRegisterDeviceInterface(
            PhysicalDeviceObject,
            &SmartCardReaderGuid,
            NULL,
            &deviceExtension->PnPDeviceName
            );
        ASSERT(status == STATUS_SUCCESS);

    	DeviceObject->Flags |= DO_BUFFERED_IO;
		DeviceObject->Flags |= DO_POWER_PAGABLE;
		DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

   }
   __finally {

		if (regKey) {

			ZwClose(regKey);
		}

        if (status != STATUS_SUCCESS) {

            TLP3RemoveDevice(DeviceObject);
        }

		SmartcardDebug( 
			DEBUG_TRACE, 
			( "%s!TLP3AddDevice: Exit %x\n",
			DRIVER_NAME,
			status)
			);

		return status;
   }
}

NTSTATUS
TLP3StartDevice(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:
	Open the serial device, start card tracking and register our
    device interface. If any of the calls here fails we don't care
    to rollback since a stop will be called later which we then
    use to clean up.

--*/
{
    NTSTATUS status;
    PIRP irp;
   	PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
	PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;

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

    irp = IoAllocateIrp(
        (CCHAR) (DeviceObject->StackSize + 1),
        FALSE
        );

    ASSERT(irp != NULL);

    if (irp == NULL) {

        return STATUS_NO_MEMORY;
    }

    _try {
     	
        PIO_STACK_LOCATION irpStack;
        HANDLE handle = 0;
        IO_STATUS_BLOCK ioStatusBlock;

        //
        // Open the underlying serial driver. 
        // This is necessary for two reasons:
        // a) The serial driver can't be used without opening it
        // b) The call will go through serenum first which informs 
        //    it to stop looking/polling for new devices.
        //
        irp->UserIosb = &ioStatusBlock;
        IoSetNextIrpStackLocation(irp);
        irpStack = IoGetCurrentIrpStackLocation(irp);

        irpStack->MajorFunction = IRP_MJ_CREATE;
        irpStack->Parameters.Create.Options = 0;
        irpStack->Parameters.Create.ShareAccess = 0;
        irpStack->Parameters.Create.FileAttributes = 0;

⌨️ 快捷键说明

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