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

📄 pscrnt.c

📁 SmartCard驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;        
    }

    AttachedPDO = DeviceExtension->AttachedPDO;

	IrpStack = IoGetCurrentIrpStackLocation(Irp);

    // Now look what the PnP manager wants...
	switch(IrpStack->MinorFunction)
	{
		case IRP_MN_START_DEVICE:

            // Now we should connect to our resources (Irql, Io etc.)
			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_START_DEVICE\n")
                );

            // We have to call the underlying driver first
            status = PscrCallPcmciaDriver(AttachedPDO, Irp);

            if (status == STATUS_SUCCESS) {

                status = PscrStartDevice(
	                DeviceObject,
                    &IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0]
                    );

                ASSERT(status == STATUS_SUCCESS);
            }
			break;

        case IRP_MN_QUERY_STOP_DEVICE:

			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_QUERY_STOP_DEVICE\n")
                );
            KeAcquireSpinLock(&DeviceExtension->SpinLock, &irql);
            if (DeviceExtension->IoCount > 0) {

                // we refuse to stop if we have pending io
                KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);
                status = STATUS_DEVICE_BUSY;

            } else {

                // stop processing requests
                KeClearEvent(&DeviceExtension->ReaderStarted);
                KeReleaseSpinLock(&DeviceExtension->SpinLock, irql);             	
                status = PscrCallPcmciaDriver(AttachedPDO, Irp);
            }
        	break;

        case IRP_MN_CANCEL_STOP_DEVICE:

			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_CANCEL_STOP_DEVICE\n")
                );

            status = PscrCallPcmciaDriver(AttachedPDO, Irp);
            ASSERT(status == STATUS_SUCCESS);

            // we can continue to process requests
            DeviceExtension->IoCount = 0;
            KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
        	break;

		case IRP_MN_STOP_DEVICE:

            // Stop the device. Aka disconnect from our resources
			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_STOP_DEVICE\n")
                );

            PscrStopDevice(DeviceObject);
            status = PscrCallPcmciaDriver(AttachedPDO, Irp);
			break;

		case IRP_MN_QUERY_REMOVE_DEVICE:

            // Remove our device
			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_QUERY_REMOVE_DEVICE\n")
                );

            // disable the reader
            status = IoSetDeviceInterfaceState(
                &DeviceExtension->DeviceName,
                FALSE
                );
            ASSERT(status == STATUS_SUCCESS);

            if (status != STATUS_SUCCESS) {

                break;
            }

            //
            // check if the reader has been opened
            //
            if (DeviceExtension->ReaderOpen) {

                // someone is connected, enable the reader and fail the call
                IoSetDeviceInterfaceState(
                    &DeviceExtension->DeviceName,
                    TRUE
                    );
                status = STATUS_UNSUCCESSFUL;
                break;
            }

            // pass the call to the next driver in the stack
            status = PscrCallPcmciaDriver(AttachedPDO, Irp);
			break;

        case IRP_MN_CANCEL_REMOVE_DEVICE:

            // Removal of device has been cancelled
			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_CANCEL_REMOVE_DEVICE\n")
                );

            status = PscrCallPcmciaDriver(AttachedPDO, Irp);

            if (status == STATUS_SUCCESS) {
             	
                status = IoSetDeviceInterfaceState(
                    &DeviceExtension->DeviceName,
                    TRUE
                    );
            }
        	break;

		case IRP_MN_REMOVE_DEVICE:

            // Remove our device
			SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPnPDeviceControl: IRP_MN_REMOVE_DEVICE\n")
                );

            KeSetEvent(&DeviceExtension->ReaderRemoved, 0, FALSE);

            PscrStopDevice(DeviceObject);
            PscrUnloadDevice(DeviceObject);

            status = PscrCallPcmciaDriver(AttachedPDO, Irp);
            deviceRemoved = TRUE;
			break;

		default:
            // This is an Irp that is only useful for underlying drivers
            status = PscrCallPcmciaDriver(AttachedPDO, Irp);
			irpSkipped = TRUE;
			break;			    
	}

	if (irpSkipped == FALSE) {

		// Don't touch the status field of irps we don't process
		Irp->IoStatus.Status = status;
	}

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    if (deviceRemoved == FALSE) {
     	
        SmartcardReleaseRemoveLock(&DeviceExtension->SmartcardExtension);
    }

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

    return status;
}

VOID
PscrSystemPowerCompletion(    
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR MinorFunction,    
    IN POWER_STATE PowerState,    
    IN PKEVENT Event,
    IN PIO_STATUS_BLOCK IoStatus    
    )
/*++

Routine Description:
    This function is called when the underlying stacks
    completed the power transition.

--*/
{ 	
    UNREFERENCED_PARAMETER (DeviceObject);
    UNREFERENCED_PARAMETER (MinorFunction);
    UNREFERENCED_PARAMETER (PowerState);
    UNREFERENCED_PARAMETER (IoStatus);

    KeSetEvent(Event, 0, FALSE);
}

NTSTATUS
PscrDevicePowerCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PSMARTCARD_EXTENSION SmartcardExtension
    )
/*++

Routine Description:
    This routine is called after the underlying stack powered
    UP the serial port, so it can be used again.

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

  	status = CmdResetInterface(SmartcardExtension->ReaderExtension);
    ASSERT(status == STATUS_SUCCESS);

	SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
    state = CBGetCardState(SmartcardExtension);

    CBUpdateCardState(SmartcardExtension, state, TRUE);                     	

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

    SmartcardReleaseRemoveLock(SmartcardExtension);

    // inform the power manager of our state.
    PoSetPowerState (
        DeviceObject,
        DevicePowerState,
        irpStack->Parameters.Power.State
        );

    PoStartNextPowerIrp(Irp);

    // signal that we can process ioctls again
    KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);

    return STATUS_SUCCESS;
}

typedef enum _ACTION {
 	
    Undefined = 0,
    SkipRequest,
    WaitForCompletion,
    CompleteRequest,
    MarkPending

} ACTION;

NTSTATUS
PscrPower (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:
    The power dispatch routine.
    This driver is the power policy owner of the device stack, 
    because this driver knows about the connected reader. 
    Therefor this driver will translate system power states
    to device power states.
    
Arguments:
   DeviceObject - pointer to a device object.
   Irp - pointer to an I/O Request Packet.

Return Value:
      NT status code

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
    POWER_STATE powerState;
    ACTION action;
	KEVENT event;

    SmartcardDebug(
        DEBUG_DRIVER,
        ("PSCR!PscrPower: Enter\n")
        );

    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    status = SmartcardAcquireRemoveLock(smartcardExtension);
    ASSERT(status == STATUS_SUCCESS);

    if (!NT_SUCCESS(status)) {

        PoStartNextPowerIrp(Irp);
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    if (irpStack->Parameters.Power.Type == DevicePowerState && 
        irpStack->MinorFunction == IRP_MN_SET_POWER) {

        switch (irpStack->Parameters.Power.State.DeviceState) {

        case PowerDeviceD0:
            // Turn on the reader
            SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPower: PowerDevice D0\n")
                );

            //
            // First, we send down the request to the bus, in order
            // to power on the port. When the request completes, 
            // we turn on the reader
            //
            IoCopyCurrentIrpStackLocationToNext(Irp);
            IoSetCompletionRoutine (
                Irp,
                PscrDevicePowerCompletion,
                smartcardExtension,
                TRUE,
                TRUE,
                TRUE
                );

            action = WaitForCompletion;
            break;    

        case PowerDeviceD3:    
            // Turn off the reader
            SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPower: PowerDevice D3\n")
                );

            PoSetPowerState (
                DeviceObject,
                DevicePowerState,
                irpStack->Parameters.Power.State
                );

            // save the current card state
            smartcardExtension->ReaderExtension->CardPresent = 
                smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;

            if (smartcardExtension->ReaderExtension->CardPresent) {
             	
                smartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
                status = CBCardPower(smartcardExtension);
                ASSERT(status == STATUS_SUCCESS);
            }

            // save the current power state of the reader
            smartcardExtension->ReaderExtension->ReaderPowerState =
                PowerReaderOff;

            action = SkipRequest;
        	break;

        default:
        	ASSERT(FALSE);
            action = SkipRequest;
            break;
        }
    }
    
    if (irpStack->Parameters.Power.Type == SystemPowerState) {

        // 
        // The system wants to change the power state.
        // We need to translate the system power state to 
        // a corresponding device power state.
        //
     	
        POWER_STATE_TYPE powerType = DevicePowerState;

        ASSERT(smartcardExtension->ReaderExtension->ReaderPowerState !=
            PowerReaderUnspecified);

        switch(irpStack->MinorFunction) { 

		KIRQL irql;

        case IRP_MN_QUERY_POWER:

            SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPower: Query Power\n")
                );

            switch (irpStack->Parameters.Power.State.SystemState) {

            case PowerSystemMaximum:
            case PowerSystemWorking:
            case PowerSystemSleeping1:
            case PowerSystemSleeping2:
				action = SkipRequest;
                break;

            case PowerSystemSleeping3:
            case PowerSystemHibernate:
            case PowerSystemShutdown:
                KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
                if (deviceExtension->IoCount == 0) {

                    // Block any further ioctls
                    KeClearEvent(&deviceExtension->ReaderStarted);
					action = SkipRequest;

                } else {
                 	
                    // can't go to sleep mode since the reader is busy.
                    status = STATUS_DEVICE_BUSY;
					action = CompleteRequest;
                }
                KeReleaseSpinLock(&deviceExtension->SpinLock, irql);             	
                break;
            }
        	break;
            
        case IRP_MN_SET_POWER:

            SmartcardDebug(
                DEBUG_DRIVER,
                ("PSCR!PscrPower: PowerSystem S%d\n",
                irpStack->Parameters.Power.State.SystemState - 1)
                );

            switch (irpStack->Parameters.Power.State.SystemState) {

            case PowerSystemMaximum:
            case PowerSystemWorking:
            case PowerSystemSleeping1:
            case PowerSystemSleeping2:

                if (smartcardExtension->ReaderExtension->ReaderPowerState == 
                    PowerReaderWorking) {

                    // We're already in the right state
					KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
					action = CompleteRequest;
                    break;
                }

                powerState.DeviceState = PowerDeviceD0;

                // wake up the underlying stack...
                action = MarkPending;
                break;

            case PowerSystemSleeping3:
            case PowerSystemHibernate:
            case PowerSystemShutdown:

                if (smartcardExtension->ReaderExtension->ReaderPowerState == 
                    PowerReaderOff) {

                    // We're already in the right state
                    action = CompleteRequest;
                    break;
                }

                powerState.DeviceState = PowerDeviceD3;
                
                // first, inform the power manager of our new state.
                PoSetPowerState (
                    DeviceObject,
                    SystemPowerState,
                    powerState
                    );

                action = MarkPending;
                break;

            default:
                ASSERT(FALSE);
                action = CompleteRequest;
                break;
            }
        }
    }

    switch (action) {

        case CompleteRequest:
            status = STATUS_SUCCESS;
            Irp->IoStatus.Status = status;
            Irp->IoStatus.Information = 0;

            SmartcardReleaseRemoveLock(smartcardExtension);
            PoStartNextPowerIrp(Irp);
            IoCompleteRequest(Irp, IO_NO_INCREMENT);     	
        	break;

        case MarkPending:

			// initialize the event we need in the completion function
			KeInitializeEvent(
				&event,
				NotificationEvent,
				FALSE
				);   

			// request the device power irp
            status = PoRequestPowerIrp (
                DeviceObject,
                IRP_MN_SET_POWER,   
                powerState,
                PscrSystemPowerCompletion,
                &event, 
                NULL              
                );
            ASSERT(status == STATUS_PENDING);

			if (status == STATUS_PENDING) {

				// wait until the device power irp completed
				status = KeWaitForSingleObject(
					&event,
					Executive,
					KernelMode,
					FALSE,
					NULL
					);

				SmartcardReleaseRemoveLock(smartcardExtension);

				if (powerState.SystemState == PowerSystemWorking) {

					PoSetPowerState (
						DeviceObject,
						SystemPowerState,
						powerState
						);
				}

				PoStartNextPowerIrp(Irp);
				IoSkipCurrentIrpStackLocation(Irp);
				status = PoCallDriver(deviceExtension->AttachedPDO, Irp);     	

			} else {

				SmartcardReleaseRemoveLock(smartcardExtension);
				Irp->IoStatus.Status = status;
			    IoCompleteRequest(Irp, IO_NO_INCREMENT);
			}

        	break;

        case SkipRequest:
            SmartcardReleaseRemoveLock(smartcardExtension);
            PoStartNextPowerIrp(Irp);
            IoSkipCurrentIrpStackLocation(Irp);
            status = PoCallDriver(deviceExtension->AttachedPDO, Irp);     	
        	break;

        case WaitForCompletion:
            status = PoCallDriver(deviceExtension->AttachedPDO, Irp);
        	break;

        default:
            ASSERT(FALSE);
            break; 	
    }

    SmartcardDebug(
        DEBUG_DRIVER,
        ("PSCR!PscrPower: Exit %lx\n",
        status)
        );

    return status;
}

NTSTATUS 

⌨️ 快捷键说明

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