/*++ 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 #include #include #include #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; }