📄 sspnp.c
字号:
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
SSDbgPrint(1, ("UsbBuildGetDescriptorRequest failed\n"));
goto ConfigureDevice_Exit;
}
}
else {
SSDbgPrint(1, ("Failed to allocate mem for config Descriptor\n"));
ntStatus = 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);
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
SSDbgPrint(1,("Failed to read configuration descriptor"));
goto ConfigureDevice_Exit;
}
}
else {
SSDbgPrint(1, ("Failed to alloc mem for config Descriptor\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
}
else {
SSDbgPrint(1, ("Failed to allocate memory for urb\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
if(configurationDescriptor) {
if(configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
{
//
// this configuration supports remote wakeup
//
deviceExtension->WaitWakeEnable = 1;
}
else
{
deviceExtension->WaitWakeEnable = 0;
}
ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
}
ConfigureDevice_Exit:
if(urb) {
ExFreePool(urb);
}
if(configurationDescriptor) {
ExFreePool(configurationDescriptor);
}
return ntStatus;
}
NTSTATUS
SelectInterfaces(
IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
/*++
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
--*/
{
LONG numberOfInterfaces,
interfaceNumber,
interfaceindex;
ULONG i;
PURB urb;
PUCHAR pInf;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
PUSBD_INTERFACE_LIST_ENTRY interfaceList,
tmp;
PUSBD_INTERFACE_INFORMATION interface;
//
// initialize the variables
//
urb = NULL;
interface = NULL;
interfaceDescriptor = NULL;
deviceExtension = 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) {
SSDbgPrint(1, ("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;
}
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
SSDbgPrint(1, ("Failed to select an interface\n"));
}
}
else {
SSDbgPrint(1, ("USBD_CreateConfigurationRequestEx failed\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if(tmp) {
ExFreePool(tmp);
}
if(urb) {
ExFreePool(urb);
}
return ntStatus;
}
NTSTATUS
DeconfigureDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is invoked when the device is removed or stopped.
This routine de-configures the usb device.
Arguments:
DeviceObject - pointer to device object
Return Value:
NT status value
--*/
{
PURB urb;
ULONG siz;
NTSTATUS ntStatus;
//
// initialize variables
//
siz = sizeof(struct _URB_SELECT_CONFIGURATION);
urb = ExAllocatePool(NonPagedPool, siz);
if(urb) {
UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
SSDbgPrint(3, ("Failed to deconfigure device\n"));
}
ExFreePool(urb);
}
else {
SSDbgPrint(1, ("Failed to allocate urb\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
NTSTATUS
CallUSBD(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*++
Routine Description:
This routine synchronously submits an urb down the stack.
Arguments:
DeviceObject - pointer to device object
Urb - USB request block
Return Value:
NT status value
--*/
{
PIRP irp;
KEVENT event;
NTSTATUS ntStatus;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
//
// initialize the variables
//
irp = NULL;
deviceExtension = DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
&event,
&ioStatus);
if(!irp) {
SSDbgPrint(1, ("IoBuildDeviceIoControlRequest failed\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = Urb;
SSDbgPrint(3, ("CallUSBD::"));
SSIoIncrement(deviceExtension);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
if(ntStatus == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = ioStatus.Status;
}
SSDbgPrint(3, ("CallUSBD::"));
SSIoDecrement(deviceExtension);
return ntStatus;
}
NTSTATUS
HandleQueryStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
SSDbgPrint(3, ("HandleQueryStopDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// If we can stop the device, we need to set the QueueState to
// HoldRequests so further requests will be queued.
//
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, PendingStop);
deviceExtension->QueueState = HoldRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
//
// wait for the existing ones to be finished.
// first, decrement this operation
//
SSDbgPrint(3, ("HandleQueryStopDevice::"));
SSIoDecrement(deviceExtension);
KeWaitForSingleObject(&deviceExtension->StopEvent,
Executive,
KernelMode,
FALSE,
NULL);
//
// We must set Irp->IoStatus.Status to STATUS_SUCCESS before
// passing it down.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
SSDbgPrint(3, ("HandleQueryStopDevice - ends\n"));
return ntStatus;
}
NTSTATUS
HandleCancelStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services Irp of minor type IRP_MN_CANCEL_STOP_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT value
--*/
{
KIRQL oldIrql;
KEVENT event;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
SSDbgPrint(3, ("HandleCancelStopDevice - begins\n"));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// Send this IRP down and wait for it to come back.
// Set the QueueState flag to AllowRequests,
// and process all the previously queued up IRPs.
//
// First check to see whether you have received cancel-stop
// without first receiving a query-stop. This could happen if someone
// above us fails a query-stop and passes down the subsequent
// cancel-stop.
//
if(PendingStop == deviceExtension->DeviceState) {
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
(PVOID)&event,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if(ntStatus == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = Irp->IoStatus.Status;
}
if(NT_SUCCESS(ntStatus)) {
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
deviceExtension->QueueState = AllowRequests;
ASSERT(deviceExtension->DeviceState == Working);
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
ProcessQueuedRequests(deviceExtension);
}
}
else {
// spurious Irp
ntStatus = STATUS_SUCCESS;
}
SSDbgPrint(3, ("HandleCancelStopDevice - ends\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -