windows-nt/Source/XPSP1/NT/drivers/wdm/input/opos/posusb/dispatch.c
2020-09-26 16:20:57 +08:00

219 lines
5 KiB
C

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
dispatch.c
Abstract: ESC/POS (serial) interface for USB Point-of-Sale devices
Author:
ervinp
Environment:
Kernel mode
Revision History:
--*/
#include <WDM.H>
#include <usbdi.h>
#include <usbdlib.h>
#include <usbioctl.h>
#include "escpos.h"
#include "debug.h"
NTSTATUS Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)
/*++
Routine Description:
Common entrypoint for all Io Request Packets
Arguments:
DeviceObject - pointer to a device object.
irp - Io Request Packet
Return Value:
NT status code.
--*/
{
DEVEXT *devExt;
PIO_STACK_LOCATION irpSp;
ULONG majorFunc, minorFunc;
BOOLEAN isPdo;
NTSTATUS status;
PARENTFDOEXT *parentFdoExt;
devExt = DeviceObject->DeviceExtension;
ASSERT(devExt->signature == DEVICE_EXTENSION_SIGNATURE);
irpSp = IoGetCurrentIrpStackLocation(irp);
/*
* Get major/minor function codes in private variables
* so we can access them after the IRP is completed.
*/
majorFunc = irpSp->MajorFunction;
minorFunc = irpSp->MinorFunction;
isPdo = devExt->isPdo;
if (isPdo){
parentFdoExt = devExt->pdoExt.parentFdoExt;
}
else {
parentFdoExt = &devExt->parentFdoExt;
}
DBG_LOG_IRP_MAJOR(irp, majorFunc, isPdo, FALSE, -1);
/*
* For all IRPs except REMOVE, we increment the PendingActionCount
* across the dispatch routine in order to prevent a race condition with
* the REMOVE_DEVICE IRP (without this increment, if REMOVE_DEVICE
* preempted another IRP, device object and extension might get
* freed while the second thread was still using it).
*/
if (!((majorFunc == IRP_MJ_PNP) && (minorFunc == IRP_MN_REMOVE_DEVICE))){
IncrementPendingActionCount(parentFdoExt);
}
if (isPdo){
POSPDOEXT *pdoExt = &devExt->pdoExt;
switch (majorFunc){
case IRP_MJ_PNP:
status = PDO_PnP(pdoExt, irp);
break;
case IRP_MJ_CREATE:
status = OpenComPort(pdoExt, irp);
break;
case IRP_MJ_CLOSE:
status = CloseComPort(pdoExt, irp);
break;
case IRP_MJ_READ:
status = ReadComPort(pdoExt, irp);
break;
case IRP_MJ_WRITE:
status = WriteComPort(pdoExt, irp);
break;
case IRP_MJ_CLEANUP:
status = CleanupIO(pdoExt, irp);
break;
case IRP_MJ_QUERY_INFORMATION:
status = QueryInfo(pdoExt, irp);
break;
case IRP_MJ_SET_INFORMATION:
status = SetInfo(pdoExt, irp);
break;
case IRP_MJ_FLUSH_BUFFERS:
status = FlushBuffers(pdoExt);
break;
case IRP_MJ_DEVICE_CONTROL:
status = Ioctl(pdoExt, irp);
break;
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
status = InternalIoctl(pdoExt, irp);
break;
case IRP_MJ_POWER:
PoStartNextPowerIrp(irp);
status = STATUS_SUCCESS;
break;
default:
/*
* For unsupported IRPs, we fail them with the default status.
*/
status = irp->IoStatus.Status;
break;
}
if (status != STATUS_PENDING){
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
}
else {
if ((majorFunc != IRP_MJ_PNP) &&
(majorFunc != IRP_MJ_CLOSE) &&
((parentFdoExt->state == STATE_REMOVING) ||
(parentFdoExt->state == STATE_REMOVED))){
/*
* While the device is being removed,
* we only pass down the PNP and CLOSE IRPs.
* We fail all other IRPs.
*/
status = irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
else {
BOOLEAN passIrpDown = FALSE;
switch (majorFunc){
case IRP_MJ_PNP:
status = FDO_PnP(parentFdoExt, irp);
break;
case IRP_MJ_POWER:
status = FDO_Power(parentFdoExt, irp);
break;
default:
/*
* For unsupported IRPs, we simply send the IRP
* down the driver stack.
*/
passIrpDown = TRUE;
break;
}
if (passIrpDown){
IoCopyCurrentIrpStackLocationToNext(irp);
status = IoCallDriver(parentFdoExt->physicalDevObj, irp);
}
}
}
/*
* Balance the increment to PendingActionCount above.
*/
if (!((majorFunc == IRP_MJ_PNP) && (minorFunc == IRP_MN_REMOVE_DEVICE))){
DecrementPendingActionCount(parentFdoExt);
}
DBG_LOG_IRP_MAJOR(irp, majorFunc, isPdo, TRUE, status);
return status;
}