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

📄 pscrnt.c

📁 SmartCard驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
PscrStartDevice(
	PDEVICE_OBJECT DeviceObject,
    PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
	)
/*++

Routine Description:
	get the actual configuration from the passed FullResourceDescriptor
	and initializes the reader hardware

Note:
	for an NT 4.00 build the resources must be translated by the HAL
  
Arguments:
	DeviceObject			context of call
	FullResourceDescriptor	actual configuration of the reader

Return Value:
	STATUS_SUCCESS
	status returned from the HAL (NT 4.00 only )
	status returned by LowLevel routines



--*/
{
	PCM_PARTIAL_RESOURCE_DESCRIPTOR	PartialDescriptor;
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
    PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
    NTSTATUS status;
	ULONG Count;

	SmartcardDebug( 
		DEBUG_TRACE, 
		("PSCR!PscrStartDevice: Enter\n")
		);

    // Get the number of resources we need
	Count = FullResourceDescriptor->PartialResourceList.Count;

	PartialDescriptor = FullResourceDescriptor->PartialResourceList.PartialDescriptors;

	//	parse all partial descriptors
	while(Count--)
	{
		switch(PartialDescriptor->Type)
		{
			case CmResourceTypePort: {
             	
                //	0 - memory,	1 - IO
                ULONG AddressSpace = 1;
                BOOLEAN Translated;
                PHYSICAL_ADDRESS PhysicalAddress;

                ReaderExtension->IOBase = 
                    (PPSCR_REGISTERS) PartialDescriptor->u.Port.Start.LowPart;

                ASSERT(PartialDescriptor->u.Port.Length >= 4);

				SmartcardDebug( 
                    DEBUG_TRACE,
					("PSCR!PscrStartDevice: IoBase = %lxh\n",
					ReaderExtension->IOBase)
					);
				break;
            }

			case CmResourceTypeInterrupt: {
             	
				KINTERRUPT_MODE	Mode;
				BOOLEAN	Shared;
				KIRQL Irql;
				KAFFINITY Affinity;
				ULONG Vector;

				Mode = ( 
					PartialDescriptor->Flags & 
					CM_RESOURCE_INTERRUPT_LATCHED ? 
					Latched : LevelSensitive
					);

				Shared = ( 
					PartialDescriptor->ShareDisposition == 
					CmResourceShareShared 
					);

				Vector = PartialDescriptor->u.Interrupt.Vector;
                Affinity = PartialDescriptor->u.Interrupt.Affinity;
                Irql = (KIRQL) PartialDescriptor->u.Interrupt.Level;

				//	store IRQ to allow query configuration
				ReaderExtension->CurrentIRQ =
					PartialDescriptor->u.Interrupt.Vector;

				SmartcardDebug( 
					DEBUG_TRACE, 
					("PSCR!PscrStartDevice: Irql: %d\n",
					PartialDescriptor->u.Interrupt.Level)
					);
				//	connect the driver's isr
				status = IoConnectInterrupt(
					&DeviceExtension->InterruptObject,
					PscrIrqServiceRoutine,
					(PVOID) DeviceExtension,		
					NULL,	
					Vector,
					Irql,
					Irql,
					Mode,
					Shared,
					Affinity,
					FALSE
					);

				break;
			}

            case CmResourceTypeDevicePrivate:
            	break;

			default:
                ASSERT(FALSE);
				status = STATUS_UNSUCCESSFUL;
				break;
		}
		PartialDescriptor++;
	}

    try {

        HANDLE handle;
        UCHAR CardState;

	    //	IOBase initialized ?
	    if( ReaderExtension->IOBase == NULL ) {

			//
			//	under NT 4.0 the failure of this fct for the second reader
			//	means there is only one device
			//
			SmartcardLogError(
				DeviceObject,
				PSCR_ERROR_IO_PORT,
				NULL,
				0
				);

            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
	    } 

	    //	irq connected ?
	    if( DeviceExtension->InterruptObject == NULL ) {

			SmartcardLogError(
			    DeviceObject,
			    PSCR_ERROR_INTERRUPT,
			    NULL,
			    0
			    );

		    status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
	    }

		ReaderExtension->Device		= DEVICE_ICC1;
		ReaderExtension->MaxRetries = PSCR_MAX_RETRIES;
    	status = CmdResetInterface( ReaderExtension );

	    SmartcardExtension->ReaderCapabilities.MaxIFSD = 
		    ReaderExtension->MaxIFSD;

        if (status != STATUS_SUCCESS) {

		    SmartcardLogError(
			    DeviceObject,
			    PSCR_CANT_INITIALIZE_READER,
			    NULL,
			    0
			    );

            leave;
        }

   		status = CmdReset(
			ReaderExtension,
			0x00,				// reader
			FALSE,				// cold reset
			NULL,				// no atr
			NULL
			);

        if (status != STATUS_SUCCESS) {

		    SmartcardLogError(
			    DeviceObject,
			    PSCR_CANT_INITIALIZE_READER,
			    NULL,
			    0
			    );

            leave;
        }

      	PscrFlushInterface(DeviceExtension->SmartcardExtension.ReaderExtension);

		CmdGetFirmwareRevision(
			DeviceExtension->SmartcardExtension.ReaderExtension
			);

        // If you change the min. firmware version here, please update
        // the .mc file for the correct error message, too
        if (SmartcardExtension->ReaderExtension->FirmwareMajor < 2 ||
            SmartcardExtension->ReaderExtension->FirmwareMajor == 2 &&
            SmartcardExtension->ReaderExtension->FirmwareMinor < 0x30) {

		    SmartcardLogError(
			    DeviceObject,
			    PSCR_WRONG_FIRMWARE,
			    NULL,
			    0
			    );
        }

		//
		//	make sure the ICC1 status file in the reader file system will
		//	be selected
		//
		ReaderExtension->StatusFileSelected = FALSE;
        CardState = CBGetCardState(&DeviceExtension->SmartcardExtension);
        CBUpdateCardState(&DeviceExtension->SmartcardExtension, CardState, FALSE);

        // signal that the reader has been started (again)
        KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);

        status = IoSetDeviceInterfaceState(
            &DeviceExtension->DeviceName,
            TRUE
            );

        if (status == STATUS_OBJECT_NAME_EXISTS) {

            // We tried to re-enable the device which is ok
            // This can happen after a stop - start sequence
            status = STATUS_SUCCESS;         	
        }
        ASSERT(status == STATUS_SUCCESS);
    }
    finally {

        if (status != STATUS_SUCCESS) {

            PscrStopDevice(DeviceObject);
        }

        SmartcardDebug( 
	        DEBUG_TRACE, 
	        ( "PSCR!PscrStartDevice: Exit %x\n", 
	        status )
	        );

        return status;     	
    }
}

VOID
PscrStopDevice( 
	PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:
	Diconnect the interrupt used by the device & unmap the IO port

--*/
{
    PDEVICE_EXTENSION DeviceExtension;
    NTSTATUS status;
	LARGE_INTEGER delayPeriod;

    if (DeviceObject == NULL) {

        return;
    }

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!PscrStopDevice: Enter\n" )
		);

    DeviceExtension = DeviceObject->DeviceExtension;
    KeClearEvent(&DeviceExtension->ReaderStarted);

	//	disconnect the interrupt
	if( DeviceExtension->InterruptObject != NULL )
	{
		IoDisconnectInterrupt(DeviceExtension->InterruptObject);
        DeviceExtension->InterruptObject = NULL;
	}

	//	unmap ports
	if(DeviceExtension->UnMapPort)
	{
		MmUnmapIoSpace( 
			DeviceExtension->SmartcardExtension.ReaderExtension->IOBase, 
			DeviceExtension->SmartcardExtension.ReaderExtension->IOWindow
			);

        DeviceExtension->UnMapPort = FALSE;
	}

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!PscrStopDevice: Exit\n" )
		);
}

VOID
PscrUnloadDevice( 
	PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:
	close connections to smclib.sys and the pcmcia driver, delete symbolic
	link and mark the slot as unused.


Arguments:
	DeviceObject	device to unload

Return Value:
	void

--*/
{
    PDEVICE_EXTENSION DeviceExtension;
    NTSTATUS status;

    if (DeviceObject == NULL) {

        return;     	
    }

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!PscrUnloadDevice: Enter\n" )
		);

    DeviceExtension = DeviceObject->DeviceExtension;

    ASSERT(
        DeviceExtension->SmartcardExtension.VendorAttr.UnitNo < 
        PSCR_MAX_DEVICE
        );


    if (DeviceExtension->DeviceName.Buffer != NULL) {
     	
        // disble our device so no one can open it
        IoSetDeviceInterfaceState(
            &DeviceExtension->DeviceName,
            FALSE
            );
    }

    // Mark this slot as available
    DeviceSlot[DeviceExtension->SmartcardExtension.VendorAttr.UnitNo] = FALSE;

	//	report to the lib that the device will be unloaded
	if(DeviceExtension->SmartcardExtension.OsData != NULL)
	{
        KIRQL CancelIrql;
        PSMARTCARD_EXTENSION SmartcardExtension = 
            &DeviceExtension->SmartcardExtension;

        ASSERT(SmartcardExtension->OsData->NotificationIrp == NULL);

	    IoAcquireCancelSpinLock( &CancelIrql );        

	    if( SmartcardExtension->OsData->NotificationIrp != NULL )
	    {
            PIRP notificationIrp;

            notificationIrp = InterlockedExchangePointer(
                &(SmartcardExtension->OsData->NotificationIrp),
                NULL
                );

		    IoSetCancelRoutine( 
                notificationIrp, 
                NULL 
                );

            IoReleaseCancelSpinLock( CancelIrql );

	        SmartcardDebug( 
		        DEBUG_TRACE, 
		        ( "PSCR!PscrUnloadDevice: Completing NotificationIrp %lx\n",
                notificationIrp)
		        );

		    //	finish the request
		    notificationIrp->IoStatus.Status = STATUS_SUCCESS;
		    notificationIrp->IoStatus.Information = 0;

		    IoCompleteRequest(
                notificationIrp, 
                IO_NO_INCREMENT 
                );

        } else {
         	
            IoReleaseCancelSpinLock( CancelIrql );
        }

        // Wait until we can safely unload the device
        SmartcardReleaseRemoveLockAndWait(SmartcardExtension);

		SmartcardExit(&DeviceExtension->SmartcardExtension);
	}

	//	delete the symbolic link
	if( DeviceExtension->DeviceName.Buffer != NULL )
	{
		RtlFreeUnicodeString(&DeviceExtension->DeviceName);
		DeviceExtension->DeviceName.Buffer = NULL;
	}

    if (DeviceExtension->SmartcardExtension.ReaderExtension != NULL) {

        ExFreePool(DeviceExtension->SmartcardExtension.ReaderExtension);
        DeviceExtension->SmartcardExtension.ReaderExtension = NULL;
    }

    // Detach from the pcmcia driver
    if (DeviceExtension->AttachedPDO) {
     
        IoDetachDevice(DeviceExtension->AttachedPDO); 
        DeviceExtension->AttachedPDO = NULL;
    }

	//	delete the device object
	IoDeleteDevice(DeviceObject);

	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!PscrUnloadDevice: Exit\n" )
		);
}

VOID
PscrUnloadDriver( 
	PDRIVER_OBJECT DriverObject 
	)
/*++

PscrUnloadDriver:
	unloads all devices for a given driver object

Arguments:
	DriverObject	context of driver

--*/
{
	SmartcardDebug( 
		DEBUG_TRACE, 
		( "PSCR!PscrUnloadDriver\n" )
		);
}

NTSTATUS 
PscrCreateClose(
	PDEVICE_OBJECT	DeviceObject,
	PIRP			Irp
	)
/*++

PscrCreateClose:
	allowes only one open process a time

Arguments:
	DeviceObject	context of device
	Irp				context of call

Return Value:
	STATUS_SUCCESS
	STATUS_DEVICE_BUSY

--*/
{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;

	__try {

		if (irpStack->MajorFunction == IRP_MJ_CREATE) {

			status = SmartcardAcquireRemoveLockWithTag(
				&deviceExtension->SmartcardExtension,
				'lCrC'
				);

			if (status != STATUS_SUCCESS) {

				status = STATUS_DEVICE_REMOVED;         	
				__leave;
			}

			// test if the device has been opened already
			if (InterlockedCompareExchange(
				&deviceExtension->ReaderOpen, 
				TRUE,
				FALSE) == FALSE) {

				SmartcardDebug(
					DEBUG_DRIVER,
					("%s!PscrCreateClose: Open\n", 
					DRIVER_NAME)
					);

			} else {
         		
				// the device is already in use
				status = STATUS_UNSUCCESSFUL;

				// release the lock
				SmartcardReleaseRemoveLockWithTag(
					&deviceExtension->SmartcardExtension, 
					'lCrC'
					);
			}

		} else {

			SmartcardDebug(
				DEBUG_DRIVER,
				("%s!PscrCreateClose: Close\n", 
				DRIVER_NAME)
				);

			SmartcardReleaseRemoveLockWithTag(
				&deviceExtension->SmartcardExtension, 
				'lCrC'
				);

			deviceExtension->ReaderOpen = FALSE;
		}
	}
	__finally {

		Irp->IoStatus.Status = status;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}

    return status;
}

NTSTATUS 
PscrDeviceIoControl(
	PDEVICE_OBJECT	DeviceObject,
	PIRP			Irp
	)
/*++

PscrDeviceIoControl:
	all IRP's requiring IO are queued to the StartIo routine, other requests 
	are served immediately
                                              
--*/
{
	PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    NTSTATUS status;
    KIRQL irql;
    LARGE_INTEGER timeout;

    KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
    if (deviceExtension->IoCount == 0) {
 
        KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
        status = KeWaitForSingleObject(
            &deviceExtension->ReaderStarted,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );
        ASSERT(status == STATUS_SUCCESS);

        KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
    } 

⌨️ 快捷键说明

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