📄 usb2com.pnp.cpp
字号:
//********************************************************************
// created: 11:7:2008 21:30
// file: usb2com.pnp.cpp
// author: tiamo
// purpose: pnp
//********************************************************************
#include "stdafx.h"
//
// pnp complete routine
//
NTSTATUS Usb2ComPnpCompleteRoutine(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp,__in PVOID Context)
{
PRKEVENT Event = static_cast<PRKEVENT>(Context);
KeSetEvent(Event,IO_NO_INCREMENT,FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// pnp dispatch routine
//
NTSTATUS Usb2ComPnp(__in PDEVICE_OBJECT DeviceObject,__in PIRP Irp)
{
PUSB2COM_DEVICE_EXTENSION DevExt = static_cast<PUSB2COM_DEVICE_EXTENSION>(DeviceObject->DeviceExtension);
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
//
// acquire remove lock
//
NTSTATUS Status = IoAcquireRemoveLock(&DevExt->RemoveLock,Irp);
if(!NT_SUCCESS(Status))
{
//
// IoAcquireRemoveLock will fail only if we have already processed IRP_MN_REMOVE_DEVICE,
// if we got here,it means someone sent us a pnp request after remove.
//
ASSERT(FALSE);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
//
// we initialize status with the value in the irp
//
Status = Irp->IoStatus.Status;
switch(IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
Status = Usb2ComStartDevice(DevExt,Irp,IrpSp);
break;
case IRP_MN_REMOVE_DEVICE:
//
// remove device
//
Usb2ComRemoveDevice(DevExt,Irp,IrpSp,FALSE);
//
// call lower driver
//
IoCopyCurrentIrpStackLocationToNext(Irp);
Status = IoCallDriver(DevExt->LowerDeviceObject,Irp);
//
// wait all outgoing irp to complete
//
IoReleaseRemoveLockAndWait(&DevExt->RemoveLock,Irp);
//
// cleanup fdo
//
Usb2ComCleanupFunctionDeviceObject(DeviceObject);
//
// return to our caller,do NOT call ReleaseRemoveLock
//
return Status;
break;
case IRP_MN_STOP_DEVICE:
Status = Usb2ComStopDevice(DevExt,Irp,IrpSp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
if(DevExt->BulkOutUrbIsRunning || DevExt->BulkInUrbIsRunning || DevExt->InterruptUrbIsRunning)
{
Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
}
else
{
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DevExt->LowerDeviceObject,Irp);
}
break;
case IRP_MN_QUERY_CAPABILITIES:
Status = Usb2ComQueryCapabilities(DevExt,Irp,IrpSp);
break;
case IRP_MN_SURPRISE_REMOVAL:
//
// remove device
//
Usb2ComRemoveDevice(DevExt,Irp,IrpSp,TRUE);
//
// pass the irp to the lower driver,we should NOT delete the device object here.
// pnp manager will send us another remove request in the later time,we will delete it in the remove quest
// fail through to the default handler
//
default:
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DevExt->LowerDeviceObject,Irp);
break;
}
IoReleaseRemoveLock(&DevExt->RemoveLock,Irp);
return Status;
}
//
// start device
//
NTSTATUS Usb2ComStartDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
//
// initialize an event
//
KEVENT Event;
KeInitializeEvent(&Event,NotificationEvent,FALSE);
//
// call the next driver
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,&Usb2ComPnpCompleteRoutine,&Event,TRUE,TRUE,TRUE);
NTSTATUS Status = IoCallDriver(DevExt->LowerDeviceObject,Irp);
if(Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,0);
Status = Irp->IoStatus.Status;
}
//
// start ourself iff the lower device started successfully
//
if(NT_SUCCESS(Status))
{
//
// config usb device
//
Status = Usb2ComConfigUsbDevice(DevExt);
if(NT_SUCCESS(Status))
{
Status = Usb2ComInitializeFIFOControl(DevExt);
if(NT_SUCCESS(Status))
{
//
// enable device interface
//
Status = IoSetDeviceInterfaceState(&DevExt->SymbolicLinkName,TRUE);
//
// setup com params
//
DevExt->Baudrate = 115200;
DevExt->SerialChars.BreakChar = 0;
DevExt->SerialChars.EofChar = 0;
DevExt->SerialChars.ErrorChar = 0;
DevExt->SerialChars.EventChar = 0;
DevExt->SerialChars.XoffChar = 0x13;
DevExt->SerialChars.XonChar = 0x11;
DevExt->SerialCommProp.CurrentRxQueue = 0x2000;
DevExt->SerialCommProp.CurrentTxQueue = 0;
DevExt->SerialCommProp.MaxBaud = SERIAL_BAUD_USER;
DevExt->SerialCommProp.MaxRxQueue = 0;
DevExt->SerialCommProp.MaxTxQueue = 0;
DevExt->SerialCommProp.PacketLength = sizeof(SERIAL_COMMPROP);
DevExt->SerialCommProp.PacketVersion = 2;
DevExt->SerialCommProp.ProvCapabilities = SERIAL_PCF_DTRDSR | SERIAL_PCF_RTSCTS | SERIAL_PCF_CD | SERIAL_PCF_PARITY_CHECK |
SERIAL_PCF_XONXOFF | SERIAL_PCF_SETXCHAR | SERIAL_PCF_TOTALTIMEOUTS | SERIAL_PCF_INTTIMEOUTS;
DevExt->SerialCommProp.ProvChar[0] = 0;
DevExt->SerialCommProp.ProvSpec1 = 0;
DevExt->SerialCommProp.ProvSpec2 = 0;
DevExt->SerialCommProp.ProvSubType = SERIAL_SP_RS232;
DevExt->SerialCommProp.Reserved1 = 0;
DevExt->SerialCommProp.ServiceMask = SERIAL_SP_SERIALCOMM;
DevExt->SerialCommProp.SettableBaud = SERIAL_BAUD_USER | SERIAL_BAUD_128K | SERIAL_BAUD_115200 | SERIAL_BAUD_57600 | SERIAL_BAUD_14400 |
SERIAL_BAUD_19200 | SERIAL_BAUD_38400 | SERIAL_BAUD_56K | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 |
SERIAL_BAUD_7200 | SERIAL_BAUD_9600 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200 |
SERIAL_BAUD_1800 | SERIAL_BAUD_075 | SERIAL_BAUD_110 | SERIAL_BAUD_150;
DevExt->SerialCommProp.SettableData = SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
DevExt->SerialCommProp.SettableParams = SERIAL_SP_PARITY | SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_STOPBITS |
SERIAL_SP_HANDSHAKING | SERIAL_SP_PARITY_CHECK | SERIAL_SP_CARRIER_DETECT;
DevExt->SerialCommProp.SettableStopParity= SERIAL_STOPBITS_10 | SERIAL_STOPBITS_20 | SERIAL_PARITY_NONE | SERIAL_PARITY_ODD |
SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK | SERIAL_PARITY_SPACE;
DevExt->SerialHandFlow.ControlHandShake = SERIAL_DTR_CONTROL;
DevExt->SerialHandFlow.FlowReplace = SERIAL_RTS_CONTROL;
DevExt->SerialHandFlow.XoffLimit = 0x400;
DevExt->SerialHandFlow.XonLimit = 0x1000;
DevExt->SerialLineControl.Parity = 0;
DevExt->SerialLineControl.StopBits = 1;
DevExt->SerialLineControl.WordLength = 8;
DevExt->SerialQueueSize.InSize = 0x1000;
DevExt->SerialQueueSize.OutSize = 0x400;
RtlZeroMemory(&DevExt->SerialStats,sizeof(DevExt->SerialStats));
RtlZeroMemory(&DevExt->SerialStatus,sizeof(DevExt->SerialStatus));
}
}
}
//
// complete this request
//
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
//
// stop device
//
NTSTATUS Usb2ComStopDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
//
// complete all irps with canceled status
//
Usb2ComCancelAllIrps(DevExt);
//
// disable usb device
//
Usb2ComDisableUsbDevice(DevExt);
return STATUS_SUCCESS;
}
NTSTATUS Usb2ComRemoveDevice(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp,__in BOOLEAN SurpriseRemoval)
{
Usb2ComCancelAllIrps(DevExt);
if(SurpriseRemoval)
DevExt->SurpriseRemoved = TRUE;
//
// if this is a surprise remove or we got a remove without a surprise remove
// then we need to clean up
//
if(SurpriseRemoval || !DevExt->SurpriseRemoved)
IoSetDeviceInterfaceState(&DevExt->SymbolicLinkName,FALSE);
return STATUS_SUCCESS;
}
//
// query capabilities
//
NTSTATUS Usb2ComQueryCapabilities(__in PUSB2COM_DEVICE_EXTENSION DevExt,__in PIRP Irp,__in PIO_STACK_LOCATION IrpSp)
{
//
// initialize an event
//
KEVENT Event;
KeInitializeEvent(&Event,NotificationEvent,FALSE);
//
// call the next driver
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,&Usb2ComPnpCompleteRoutine,&Event,TRUE,TRUE,TRUE);
NTSTATUS Status = IoCallDriver(DevExt->LowerDeviceObject,Irp);
if(Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,0);
Status = Irp->IoStatus.Status;
}
if(NT_SUCCESS(Status))
{
PDEVICE_CAPABILITIES Capabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
if(Capabilities)
{
Capabilities->EjectSupported = TRUE;
Capabilities->Removable = TRUE;
Capabilities->SurpriseRemovalOK = TRUE;
Capabilities->WarmEjectSupported = TRUE;
RtlCopyMemory(&DevExt->DeviceCapabilities,Capabilities,sizeof(DEVICE_CAPABILITIES));
}
}
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -