219 lines
5 KiB
C
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;
|
||
|
}
|
||
|
|
||
|
|