📄 pnp.c
字号:
/*
**********************************************************************
* Micrium, Inc.
* 949 Crestview Circle
* Weston, FL 33327-1848
*
* uC/USB-Bulk
*
* (c) Copyright 2003 - 2004, Micrium, Inc.
* All rights reserved.
*
***********************************************************************
----------------------------------------------------------------------
File : pnp.c
Purpose : Part of the USB bulk driver
---------------------------END-OF-HEADER------------------------------
*/
#include "Main.h"
/*********************************************************************
*
* _DeleteDevice
*/
static NTSTATUS _DeleteDevice(PDEVICE_OBJECT DeviceObject) {
NTSTATUS ntS;
UNICODE_STRING uDevUsrPath;
RtlInitUnicodeString(&uDevUsrPath, DOS_DEVICE_NAME);
ntS = IoDeleteSymbolicLink(&uDevUsrPath);
IoDeleteDevice(DeviceObject);
return(ntS);
}
/*********************************************************************
*
* _CanStopDevice
*/
static NTSTATUS _CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
return STATUS_SUCCESS;
}
/*********************************************************************
*
* _CanRemoveDevice
*/
static NTSTATUS _CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
return(STATUS_SUCCESS);
}
/*********************************************************************
*
* ReleaseMemory
*/
static NTSTATUS ReleaseMemory(IN PDEVICE_OBJECT DeviceObject) {
DEVICE_EXTENSION * DevExt;
DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
if (DevExt->UsbConfigurationDescriptor) {
ExFreePool(DevExt->UsbConfigurationDescriptor);
DevExt->UsbConfigurationDescriptor = NULL;
}
if (DevExt->UsbInterface) {
ExFreePool(DevExt->UsbInterface);
DevExt->UsbInterface = NULL;
}
if (DevExt->PipeContext) {
ExFreePool(DevExt->PipeContext);
DevExt->PipeContext = NULL;
}
return(STATUS_SUCCESS);
}
/*********************************************************************
*
* IrpCompletionRoutine
*
* Routine Description:
* This routine is a completion routine.
* In this routine we set an event.
* Since the completion routine returns
* STATUS_MORE_PROCESSING_REQUIRED, the Irps,
* which set this routine as the completion routine,
* should be marked pending.
*
* Arguments:
* DeviceObject - pointer to device object
* Irp - I/O request packet
* Context -
*
* Return Value:
* NT status value
*/
static NTSTATUS IrpCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
KEVENT * pEvent = Context;
KeSetEvent(pEvent, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*********************************************************************
*
* ReadandSelectDescriptors
*
* Function description
* Config USB device (get device+config descriptor)
*/
NTSTATUS ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject) {
URB * urb;
ULONG siz;
NTSTATUS ntS;
PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
urb = NULL;
deviceDescriptor = NULL;
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb) {
siz = sizeof(USB_DEVICE_DESCRIPTOR);
deviceDescriptor = ExAllocatePool(NonPagedPool, siz);
if (deviceDescriptor) {
UsbBuildGetDescriptorRequest(urb, (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
deviceDescriptor, NULL, siz, NULL);
ntS = CallUSBD(DeviceObject, urb);
if (NT_SUCCESS(ntS)) {
ASSERT(deviceDescriptor->bNumConfigurations);
ntS = ConfigureDevice(DeviceObject);
}
ExFreePool(urb);
ExFreePool(deviceDescriptor);
} else {
DPRINT(("<usb> error: allocating deviceDescriptor"));
ExFreePool(urb);
ntS = STATUS_INSUFFICIENT_RESOURCES;
}
} else {
DPRINT(("<usb> error: allocating urb"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
}
return(ntS);
}
/*********************************************************************
*
* SelectInterfaces
*
* Routine Description:
* This helper routine selects the configuration
* Arguments:
* DeviceObject - pointer to device object
* ConfigurationDescriptor - pointer to the configuration descriptor for the device
* Return Value:
* NT status value
*/
NTSTATUS SelectInterfaces(IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
LONG numberOfInterfaces,
interfaceNumber,
interfaceindex;
ULONG i;
PURB urb;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
PUSBD_INTERFACE_LIST_ENTRY interfaceList,
tmp;
PUSBD_INTERFACE_INFORMATION Interface;
//
// initialize the variables
//
urb = NULL;
Interface = NULL;
interfaceDescriptor = NULL;
DevExt = DeviceObject->DeviceExtension;
numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
interfaceindex = interfaceNumber = 0;
//
// Parse the configuration descriptor for the interface;
//
tmp = interfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
if(!tmp) {
DPRINT(("Failed to allocate mem for interfaceList\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
while(interfaceNumber < numberOfInterfaces) {
interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
ConfigurationDescriptor,
interfaceindex,
0, -1, -1, -1);
if(interfaceDescriptor) {
interfaceList->InterfaceDescriptor = interfaceDescriptor;
interfaceList->Interface = NULL;
interfaceList++;
interfaceNumber++;
}
interfaceindex++;
}
interfaceList->InterfaceDescriptor = NULL;
interfaceList->Interface = NULL;
urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
if(urb) {
Interface = &urb->UrbSelectConfiguration.Interface;
for(i=0; i<Interface->NumberOfPipes; i++) {
//
// perform pipe initialization here
// set the transfer size and any pipe flags we use
// USBD sets the rest of the Interface struct members
//
Interface->Pipes[i].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
}
ntS = CallUSBD(DeviceObject, urb);
if(NT_SUCCESS(ntS)) {
//
// save a copy of interface information in the device extension.
//
DevExt->UsbInterface = ExAllocatePool(NonPagedPool, Interface->Length);
if(DevExt->UsbInterface) {
RtlCopyMemory(DevExt->UsbInterface, Interface, Interface->Length);
} else {
ntS = STATUS_INSUFFICIENT_RESOURCES;
DPRINT(("memory alloc for UsbInterface failed\n"));
}
//
// Dump the interface to the debugger
//
Interface = &urb->UrbSelectConfiguration.Interface;
/*
DPRINT(("<usb> *********************** Interface info\n"));
DPRINT(("<usb> NumberOfPipes 0x%x\n", Interface->NumberOfPipes));
DPRINT(("<usb> Length 0x%x\n", Interface->Length));
DPRINT(("<usb> Alt Setting 0x%x\n", Interface->AlternateSetting));
DPRINT(("<usb> Interface Number 0x%x\n", Interface->InterfaceNumber));
DPRINT(("<usb> Class, subclass, protocol 0x%x 0x%x 0x%x\n",
Interface->Class,
Interface->SubClass,
Interface->Protocol));
*/
//
// Initialize the PipeContext
// Dump the pipe info
//
DevExt->PipeContext = ExAllocatePool( NonPagedPool, Interface->NumberOfPipes * sizeof(USB_PIPE_CONTEXT));
if(DevExt->PipeContext) {
for(i=0; i<Interface->NumberOfPipes; i++) {
DevExt->PipeContext[i].PipeOpen = FALSE;
}
} else {
ntS = STATUS_INSUFFICIENT_RESOURCES;
DPRINT(("memory alloc for UsbInterface failed\n"));
}
/*
for (i = 0; i < Interface->NumberOfPipes; i++) {
DPRINT(("<usb> *********************** Pipe info %d\n", i));
DPRINT(("<usb> PipeType 0x%x\n", Interface->Pipes[i].PipeType));
DPRINT(("<usb> EndpointAddress 0x%x\n", Interface->Pipes[i].EndpointAddress));
DPRINT(("<usb> MaxPacketSize 0x%x\n", Interface->Pipes[i].MaximumPacketSize));
DPRINT(("<usb> Interval 0x%x\n", Interface->Pipes[i].Interval));
DPRINT(("<usb> Handle 0x%x\n", Interface->Pipes[i].PipeHandle));
DPRINT(("<usb> MaximumTransferSize 0x%x\n", Interface->Pipes[i].MaximumTransferSize));
}
*/
} else {
DPRINT(("Failed to select an interface\n"));
}
} else {
DPRINT(("USBD_CreateConfigurationRequestEx failed\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
}
if(tmp) {
ExFreePool(tmp);
}
if(urb) {
ExFreePool(urb);
}
return(ntS);
}
/*********************************************************************
*
* IssueWaitWake
*
* Routine Description:
* This routine will PoRequest a WAIT WAKE irp for the device
*
* Arguments:
* DeviceExtension - pointer to device extension
*
* Return Value:
* NT status value.
*/
NTSTATUS IssueWaitWake(IN DEVICE_EXTENSION * DeviceExtension ) {
POWER_STATE poState;
NTSTATUS ntS;
DPRINT(("IssueWaitWake - begins\n"));
if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) {
return STATUS_DEVICE_BUSY;
}
InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
//
// lowest state from which this Irp will wake the system
//
poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
ntS = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject,
IRP_MN_WAIT_WAKE,
poState,
(PREQUEST_POWER_COMPLETE) WaitWakeCallback,
DeviceExtension,
&DeviceExtension->WaitWakeIrp);
if(!NT_SUCCESS(ntS)) {
InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
}
DPRINT(("IssueWaitWake - ends\n"));
return ntS;
}
NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
KIRQL oldIrql;
KEVENT startDeviceEvent;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
DPRINT(("<usb> -> HandleStartDevice\n"));
DevExt = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
DevExt->UsbConfigurationDescriptor = NULL;
DevExt->UsbInterface = NULL;
DevExt->PipeContext = NULL;
// we must start driver that are below us before sending any non-PNP IRP
KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&startDeviceEvent, TRUE, TRUE, TRUE);
// wake up lower driver
ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
if (ntS == STATUS_PENDING) {
KeWaitForSingleObject(&startDeviceEvent, Executive, KernelMode, FALSE, NULL);
ntS = Irp->IoStatus.Status;
}
if (NT_SUCCESS(ntS)) {
// read device/config/interface descriptors
ntS = ReadandSelectDescriptors(DeviceObject);
if (NT_SUCCESS(ntS)) {
// enable symbolic link for system components
ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, TRUE);
if(NT_SUCCESS(ntS)) {
KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(DevExt, Working);
DevExt->QueueState = AllowRequests;
KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
// initialize wait wake outstanding flag to false and issue a wait wake.
DevExt->FlagWWOutstanding = 0;
DevExt->FlagWWCancel = 0;
DevExt->WaitWakeIrp = NULL;
if (DevExt->WaitWakeEnable) {
IssueWaitWake(DevExt);
}
ProcessQueuedRequests(DevExt);
} else {
DPRINT(("<usb> error: HandleStartDevice::IoSetDeviceInterfaceState %x\n", ntS));
}
} else {
DPRINT(("<usb> error: HandleStartDevice::ReadandSelectDescriptors %x\n", ntS));
}
} else {
DPRINT(("<usb> error: HandleStartDevice::IoCallDriver %x\n", ntS));
}
return(ntS);
}
NTSTATUS ConfigureDevice(IN PDEVICE_OBJECT DeviceObject) {
PURB urb;
ULONG siz;
NTSTATUS ntS;
DEVICE_EXTENSION * DevExt;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
DPRINT(("<usb> -> ConfigureDevice\n"));
urb = NULL;
configurationDescriptor = NULL;
DevExt = DeviceObject->DeviceExtension;
urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if(urb) {
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if(configurationDescriptor) {
UsbBuildGetDescriptorRequest(urb, (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0,
configurationDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR), NULL);
ntS = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: CallUSBD %x\n", ntS));
goto ConfigureDevice_Exit;
}
} else {
DPRINT(("<usb> error: allocating configDescriptor\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
siz = configurationDescriptor->wTotalLength;
ExFreePool(configurationDescriptor);
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if (configurationDescriptor) {
UsbBuildGetDescriptorRequest(urb, (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, configurationDescriptor,
NULL, siz, NULL);
ntS = CallUSBD(DeviceObject, urb);
if (!NT_SUCCESS(ntS)) {
DPRINT(("<usb> error: CallUSBD %x\n", ntS));
goto ConfigureDevice_Exit;
}
} else {
DPRINT(("<usb> error: allocating configDescriptor\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
} else {
DPRINT(("<usb> error: allocating urb\n"));
ntS = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
if (configurationDescriptor) {
// keep copy of config descriptor
DevExt->UsbConfigurationDescriptor = configurationDescriptor;
if(configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK) {
DPRINT(("<usb> WaitWake enable\n"));
DevExt->WaitWakeEnable = 1;
} else {
DPRINT(("<usb> WaitWake disable\n"));
DevExt->WaitWakeEnable = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -