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

📄 waitmask.c

📁 usb to rs232 虚拟RS232串口驱动程序
💻 C
字号:
/*++

Copyright (c) 2005-2006  E0 Technology,Inc.

Module Name:

	waitmask.c

Abstract:

	Virtual Com Port Driver for USB to RS232 Converter of E0 Technology,Inc.

Environment:

	Kernel mode

Notes:

Revision History:

    2006/3/1 : 	Adapted from the serial DDK sample.
--*/

#include "usb2com.h"

void
SerialCancelCurrentWait( PDEVICE_OBJECT DeviceObject, PIRP pIrp )
{
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION deviceExtension;
	
	DbgPrint("SerialCancelCurrentWait Enter Irp = %p\n",pIrp);
	ASSERT(pIrp);
	irpStack = IoGetCurrentIrpStackLocation(pIrp);
	deviceExtension = irpStack->DeviceObject->DeviceExtension;
	deviceExtension->CurrentWaitIrp = NULL;
	/*
	*All Cancel routines must follow these guidelines:
	* 1. Call IoReleaseCancelSpinLock to release the system's cancel spin lock
	* 2. ...
	*/
	IoReleaseCancelSpinLock(pIrp->CancelIrql);
	pIrp->IoStatus.Status = STATUS_CANCELLED;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	DbgPrint("SerialCancelCurrentWait Exit\n");
}

NTSTATUS
SerialCompleteCurrentWait(PIRP pIrp, ULONG events)
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	KIRQL OldIrql;
	PDRIVER_CANCEL oldCancelRoutine;
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION deviceExtension;
	PIRP WaitIrp;

	DbgPrint("SerialCompleteCurrentWait Irp = %p events = %x\n",pIrp,events);
	irpStack = IoGetCurrentIrpStackLocation(pIrp);
	deviceExtension = irpStack->DeviceObject->DeviceExtension;
	IoAcquireCancelSpinLock(&OldIrql);
	oldCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
	if (pIrp->Cancel){
	    //  The IRP was canceled.  Check whether our cancel routine was called.
	    if (oldCancelRoutine){
	        //  The cancel routine was NOT called.  
		irpStack = IoGetCurrentIrpStackLocation(pIrp);
		SerialCancelCurrentWait(irpStack->DeviceObject,pIrp);
	    }else {
	        //  The cancel routine WAS called.  
	        //  As soon as we drop our spin lock it will dequeue and complete the IRP.
	        //  So leave the IRP in the queue and otherwise don't touch it.
	        //  Return pending since we're not completing the IRP here.
	    }  //end else
	    IoReleaseCancelSpinLock(OldIrql);
	    return STATUS_CANCELLED;
	} // endif
	deviceExtension->CurrentWaitIrp = NULL;
	deviceExtension->HistoryMask &= ~events;
	IoReleaseCancelSpinLock(OldIrql);
	pIrp->IoStatus.Information = sizeof(ULONG);
	pIrp->IoStatus.Status = ntStatus;
	*((ULONG *)pIrp->AssociatedIrp.SystemBuffer) = events;
	IoCompleteRequest (pIrp,IO_NO_INCREMENT);
	DbgPrint("SerialCompleteCurrentWait Exit\n");
	return ntStatus;
}

NTSTATUS
SerialSetWaitMask(PIRP pIrp )
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	ULONG NewMask;
	KIRQL OldIrql;
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION deviceExtension;
	
	DbgPrint("SerialSetWaitMask Irp = %p\n",pIrp);
	ASSERT(pIrp);
	irpStack = IoGetCurrentIrpStackLocation(pIrp);
	deviceExtension = irpStack->DeviceObject->DeviceExtension;
	
	NewMask = *((ULONG *)pIrp->AssociatedIrp.SystemBuffer);
	//
	// Make sure that the mask only contains valid
	// waitable events.
	//
	if (NewMask & ~(SERIAL_EV_RXCHAR   |
                            SERIAL_EV_RXFLAG   |
                            SERIAL_EV_TXEMPTY  |
                            SERIAL_EV_CTS      |
                            SERIAL_EV_DSR      |
                            SERIAL_EV_RLSD     |
                            SERIAL_EV_BREAK    |
                            SERIAL_EV_ERR      |
                            SERIAL_EV_RING     |
                            SERIAL_EV_PERR     |
                            SERIAL_EV_RX80FULL |
                            SERIAL_EV_EVENT1   |
                            SERIAL_EV_EVENT2)) {

                ntStatus = STATUS_INVALID_PARAMETER;
                return ntStatus;
	}
	/*
	*If a wait-on-mask request is already pending when a set-wait-mask request is processed,
	*the pending wait-on-event request is completed with a status of STATUS_SUCCESS
	*and the output wait event mask is set to zero.
	*/
	IoAcquireCancelSpinLock(&OldIrql);
	if(deviceExtension->CurrentWaitIrp)
	{
		IoReleaseCancelSpinLock(OldIrql);
		SerialCompleteCurrentWait(deviceExtension->CurrentWaitIrp,0);
	}else
		IoReleaseCancelSpinLock(OldIrql);
	deviceExtension->WaitMask = NewMask;
	DbgPrint("SerialSetWaitMask Exit\n");
	return ntStatus;
}

NTSTATUS
SerialWaitOnMask(PIRP	pIrp)
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
	ULONG NewMask;
	KIRQL OldIrql;
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION deviceExtension;
	ULONG events;

	DbgPrint("SerialWaitOnMask Enter Irp = %p\n",pIrp);
	irpStack = IoGetCurrentIrpStackLocation(pIrp);
	deviceExtension = irpStack->DeviceObject->DeviceExtension;
	//
	// First make sure that we have a non-zero mask.
	// If the app queues a wait on a zero mask it can't
	// be statisfied so it makes no sense to start it.
	//
	IoAcquireCancelSpinLock(&OldIrql);
	if ((!deviceExtension->WaitMask) || (deviceExtension->CurrentWaitIrp))
	{
		IoReleaseCancelSpinLock(OldIrql);
		ntStatus = STATUS_INVALID_PARAMETER;
		pIrp->IoStatus.Information = 0;
		pIrp->IoStatus.Status = ntStatus;
    		IoCompleteRequest (
    			pIrp,
			IO_NO_INCREMENT
			);
		return	ntStatus;
	}else{
		IoReleaseCancelSpinLock(OldIrql);
	}

	IoAcquireCancelSpinLock(&OldIrql);
	events = deviceExtension->WaitMask & deviceExtension->HistoryMask;
	if ( events )
	{
		IoReleaseCancelSpinLock(OldIrql);
		ntStatus = SerialCompleteCurrentWait(pIrp,events);
	}else
	{
		deviceExtension->CurrentWaitIrp = pIrp;
		IoSetCancelRoutine(
			pIrp,
			SerialCancelCurrentWait
		);
		IoReleaseCancelSpinLock(OldIrql);
      		IoMarkIrpPending(pIrp);
      		ntStatus = STATUS_PENDING;
    	}
    	DbgPrint("SerialWaitOnMask Exit\n");
	return ntStatus;
}

⌨️ 快捷键说明

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