?? pnp.c
字號:
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
pnp.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"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FDO_PnP)
#pragma alloc_text(PAGE, GetDeviceCapabilities)
#endif
NTSTATUS FDO_PnP(PARENTFDOEXT *parentFdoExt, PIRP irp)
/*++
Routine Description:
Dispatch routine for PnP IRPs (MajorFunction == IRP_MJ_PNP)
Arguments:
parentFdoExt - device extension for the targetted device object
irp - IO Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN completeIrpHere = FALSE;
BOOLEAN justReturnStatus = FALSE;
ULONG minorFunction;
enum deviceState prevState;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(irp);
/*
* Get this field into a stack var so we can touch it after the IRP's completed.
*/
minorFunction = (ULONG)(irpSp->MinorFunction);
DBG_LOG_PNP_IRP(irp, minorFunction, FALSE, FALSE, -1);
switch (minorFunction){
case IRP_MN_START_DEVICE:
prevState = parentFdoExt->state;
parentFdoExt->state = STATE_STARTING;
/*
* First, send the START_DEVICE irp down the stack
* synchronously to start the lower stack.
* We cannot do anything with our device object
* before propagating the START_DEVICE this way.
*/
IoCopyCurrentIrpStackLocationToNext(irp);
status = CallNextDriverSync(parentFdoExt, irp);
if (NT_SUCCESS(status) && (prevState != STATE_STOPPED)){
/*
* Now that the lower stack is started,
* do any initialization required by this device object.
*/
status = GetDeviceCapabilities(parentFdoExt);
if (NT_SUCCESS(status)){
status = InitUSB(parentFdoExt);
if (NT_SUCCESS(status)){
/*
* Check whether any special feature needs to be implemented.
*/
DBGVERBOSE(("FDO_PnP: Poking registry for posFlag..."));
status = QuerySpecialFeature(parentFdoExt);
if (NT_SUCCESS(status)){
status = CreatePdoForEachEndpointPair(parentFdoExt);
if (NT_SUCCESS(status)){
IoInvalidateDeviceRelations(parentFdoExt->physicalDevObj, BusRelations);
}
}
}
}
}
if (NT_SUCCESS(status)){
parentFdoExt->state = STATE_STARTED;
}
else {
parentFdoExt->state = STATE_START_FAILED;
}
completeIrpHere = TRUE;
break;
case IRP_MN_QUERY_STOP_DEVICE:
break;
case IRP_MN_STOP_DEVICE:
if (parentFdoExt->state == STATE_SUSPENDED){
status = STATUS_DEVICE_POWER_FAILURE;
completeIrpHere = TRUE;
}
else {
/*
* Only set state to STOPPED if the device was
* previously started successfully.
*/
if (parentFdoExt->state == STATE_STARTED){
parentFdoExt->state = STATE_STOPPED;
}
}
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
/*
* We will pass this IRP down the driver stack.
* However, we need to change the default status
* from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
*/
irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
/*
* We will pass this IRP down the driver stack.
* However, we need to change the default status
* from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
*/
irp->IoStatus.Status = STATUS_SUCCESS;
/*
* For now just set the STATE_REMOVING state so that
* we don't do any more IO. We are guaranteed to get
* IRP_MN_REMOVE_DEVICE soon; we'll do the rest of
* the remove processing there.
*/
parentFdoExt->state = STATE_REMOVING;
break;
case IRP_MN_REMOVE_DEVICE:
/*
* Check the current state to guard against multiple
* REMOVE_DEVICE IRPs.
*/
parentFdoExt->state = STATE_REMOVED;
/*
* Send the REMOVE IRP down the stack asynchronously.
* Do not synchronize sending down the REMOVE_DEVICE
* IRP, because the REMOVE_DEVICE IRP must be sent
* down and completed all the way back up to the sender
* before we continue.
*/
IoCopyCurrentIrpStackLocationToNext(irp);
status = IoCallDriver(parentFdoExt->physicalDevObj, irp);
justReturnStatus = TRUE;
DBGVERBOSE(("REMOVE_DEVICE - waiting for %d irps to complete...", parentFdoExt->pendingActionCount));
/*
* We must for all outstanding IO to complete before
* completing the REMOVE_DEVICE IRP.
*
* First do an extra decrement on the pendingActionCount.
* This will cause pendingActionCount to eventually
* go to -1 once all asynchronous actions on this
* device object are complete.
* Then wait on the event that gets set when the
* pendingActionCount actually reaches -1.
*/
DecrementPendingActionCount(parentFdoExt);
KeWaitForSingleObject( &parentFdoExt->removeEvent,
Executive, // wait reason
KernelMode,
FALSE, // not alertable
NULL ); // no timeout
DBGVERBOSE(("REMOVE_DEVICE - ... DONE waiting. "));
/*
* Detach our device object from the lower device object stack.
*/
IoDetachDevice(parentFdoExt->topDevObj);
/*
* Delete all child PDOs.
*/
if (ISPTR(parentFdoExt->deviceRelations)){
ULONG i;
DBGVERBOSE(("Parent deleting %xh child PDOs on REMOVE_DEVICE", parentFdoExt->deviceRelations->Count));
for (i = 0; i < parentFdoExt->deviceRelations->Count; i++){
PDEVICE_OBJECT childPdo = parentFdoExt->deviceRelations->Objects[i];
DEVEXT *devExt = childPdo->DeviceExtension;
POSPDOEXT *pdoExt;
ASSERT(devExt->signature == DEVICE_EXTENSION_SIGNATURE);
ASSERT(devExt->isPdo);
pdoExt = &devExt->pdoExt;
DeleteChildPdo(pdoExt);
}
FREEPOOL(parentFdoExt->deviceRelations);
parentFdoExt->deviceRelations = BAD_POINTER;
}
if (ISPTR(parentFdoExt->interfaceInfo)){
FREEPOOL(parentFdoExt->interfaceInfo);
}
if (ISPTR(parentFdoExt->configDesc)){
FREEPOOL(parentFdoExt->configDesc);
}
/*
* Delete our device object.
* This will also delete the associated device extension.
*/
IoDeleteDevice(parentFdoExt->functionDevObj);
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (irpSp->Parameters.QueryDeviceRelations.Type == BusRelations){
status = QueryDeviceRelations(parentFdoExt, irp);
if (NT_SUCCESS(status)){
/*
* Although we may have satisfied this IRP,
* we still pass it down the stack.
* But change the default status to success.
*/
irp->IoStatus.Status = status;
}
else {
completeIrpHere = TRUE;
}
}
break;
case IRP_MN_QUERY_CAPABILITIES:
/*
* Return the USB PDO's capabilities, but add the SurpriseRemovalOK bit.
*/
ASSERT(irpSp->Parameters.DeviceCapabilities.Capabilities);
IoCopyCurrentIrpStackLocationToNext(irp);
status = CallNextDriverSync(parentFdoExt, irp);
if (NT_SUCCESS(status)){
irpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
}
completeIrpHere = TRUE;
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
break;
default:
break;
}
if (justReturnStatus){
/*
* We've already sent this IRP down the stack asynchronously.
*/
}
else if (completeIrpHere){
ASSERT(status != NO_STATUS);
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
else {
IoCopyCurrentIrpStackLocationToNext(irp);
status = IoCallDriver(parentFdoExt->physicalDevObj, irp);
}
DBG_LOG_PNP_IRP(irp, minorFunction, FALSE, TRUE, status);
return status;
}
NTSTATUS GetDeviceCapabilities(PARENTFDOEXT *parentFdoExt)
/*++
Routine Description:
Function retrieves the DEVICE_CAPABILITIES descriptor from the device
Arguments:
parentFdoExt - device extension for targetted device object
Return Value:
NT status code
--*/
{
NTSTATUS status;
PIRP irp;
PAGED_CODE();
irp = IoAllocateIrp(parentFdoExt->physicalDevObj->StackSize, FALSE);
if (irp){
PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(irp);
nextSp->MajorFunction = IRP_MJ_PNP;
nextSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
RtlZeroMemory( &parentFdoExt->deviceCapabilities,
sizeof(DEVICE_CAPABILITIES));
nextSp->Parameters.DeviceCapabilities.Capabilities =
&parentFdoExt->deviceCapabilities;
/*
* For any IRP you create, you must set the default status
* to STATUS_NOT_SUPPORTED before sending it.
*/
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
status = CallNextDriverSync(parentFdoExt, irp);
IoFreeIrp(irp);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
ASSERT(NT_SUCCESS(status));
return status;
}
NTSTATUS QueryDeviceRelations(PARENTFDOEXT *parentFdoExt, PIRP irp)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(irp);
if (irpSp->Parameters.QueryDeviceRelations.Type == BusRelations){
DBGVERBOSE(("QueryDeviceRelations(BusRelations) for parent"));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -