NTSTATUS BulkUsb_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PTDeviceExtension deviceExtension; SYSCTL_IRP_DISPOSITION disposition; NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation (Irp); deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; if(REMOVED == deviceExtension->DeviceState) { ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n")); BulkUsb_IoIncrement(deviceExtension); ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo, DeviceObject, Irp, &disposition); switch(disposition) { case IrpProcessed: break; case IrpNotCompleted: IoCompleteRequest(Irp, IO_NO_INCREMENT); break; case IrpForward: case IrpNotWmi: IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; default: IoSkipCurrentIrpStackLocation (Irp); ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); break; } BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_DispatchSysCtrl::\n")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
static VOID IdleNotificationCallback(IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KEVENT irpCompletionEvent; PTIrpCompletionContext irpContext; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - process\n")); if(DeviceExtension->DeviceState != WORKING) return; if(DeviceExtension->WaitWakeEnable) IssueWaitWake(DeviceExtension); irpContext = (PTIrpCompletionContext)ExAllocatePool(NonPagedPool, sizeof(TIrpCompletionContext)); if(!irpContext) { BulkUsb_DbgPrint(1, ("file bulkdev: Failed to alloc memory for irpContext\n")); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; return; } BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = DeviceExtension->PowerDownLevel; KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE); irpContext->DeviceExtension = DeviceExtension; irpContext->Event = &irpCompletionEvent; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc, irpContext, NULL); if(STATUS_PENDING == ntStatus) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback::" "waiting for the power irp to complete\n")); KeWaitForSingleObject(&irpCompletionEvent, Executive, KernelMode, FALSE, NULL); } ExFreePool(irpContext); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationCallback - ends\n")); }
//==================== NTSTATUS BulkUsb_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ULONG code; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG info; NTSTATUS ntStatus; PTDeviceExtension deviceExtension; PIO_STACK_LOCATION irpStack; info = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); code = irpStack->Parameters.DeviceIoControl.IoControlCode; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if(deviceExtension->DeviceState != WORKING) { BulkUsb_DbgPrint(1, ("file bulkdev: Invalid device state\n")); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoIncrement(deviceExtension); BulkUsb_DbgPrint(3, ("file bulkdev: Waiting on the IdleReqPendEvent\n")); if(deviceExtension->SSEnable) { KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL); } switch(code) { case IOCTL_BULKUSB_RESET_PIPE: { PFILE_OBJECT fileObject; PUSBD_PIPE_INFORMATION pipe; pipe = NULL; fileObject = irpStack->FileObject; if(fileObject == NULL) { ntStatus = STATUS_INVALID_PARAMETER; break; } pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext; if(pipe == NULL) ntStatus = STATUS_INVALID_PARAMETER; else ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe); break; } case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR: { ULONG length; if(deviceExtension->UsbConfigurationDescriptor) { length = deviceExtension->UsbConfigurationDescriptor->wTotalLength; if(outputBufferLength >= length) { RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length); info = length; ntStatus = STATUS_SUCCESS; } else ntStatus = STATUS_BUFFER_TOO_SMALL; } else ntStatus = STATUS_UNSUCCESSFUL; break; } case IOCTL_BULKUSB_RESET_DEVICE: ntStatus = BulkUsb_ResetDevice(DeviceObject); break; default : ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
static NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PTDeviceExtension DeviceExtension) { NTSTATUS ntStatus; POWER_STATE powerState; KIRQL oldIrql; LARGE_INTEGER dueTime; PIRP idleIrp; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - begins\n")); idleIrp = NULL; ntStatus = Irp->IoStatus.Status; if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) { BulkUsb_DbgPrint(1, ("file bulkdev: Idle irp completes with error::")); switch(ntStatus) { case STATUS_INVALID_DEVICE_REQUEST: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_INVALID_DEVICE_REQUEST\n")); break; case STATUS_CANCELLED: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_CANCELLED\n")); break; case STATUS_POWER_STATE_INVALID: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_POWER_STATE_INVALID\n")); goto IdleNotificationRequestComplete_Exit; case STATUS_DEVICE_BUSY: BulkUsb_DbgPrint(1, ("file bulkdev: STATUS_DEVICE_BUSY\n")); break; default: BulkUsb_DbgPrint(1, ("file bulkdev: default: status = %X\n", ntStatus)); break; } if(PowerDeviceD0 != DeviceExtension->DevPower) { BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestComplete::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, DeviceExtension, NULL); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("file bulkdev: PoRequestPowerIrp failed\n")); } } } IdleNotificationRequestComplete_Exit: KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); idleCallbackInfo = DeviceExtension->IdleCallbackInfo; DeviceExtension->IdleCallbackInfo = NULL; idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } if(idleIrp) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine has a valid irp and frees it\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } else { if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("file bulkdev: completion routine frees the irp\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } if(DeviceExtension->SSEnable) { BulkUsb_DbgPrint(3, ("file bulkdev: Set the timer to fire DPCs\n")); dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, // 5000 ms &DeviceExtension->DeferredProcCall); BulkUsb_DbgPrint(3, ("file bulkdev: IdleNotificationRequestCompete - ends\n")); } return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS BulkUsb_DispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: The power dispatch routine. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT status code --*/ { NTSTATUS ntStatus; PIO_STACK_LOCATION irpStack; PUNICODE_STRING tagString; PDEVICE_EXTENSION deviceExtension; // // initialize the variables // irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // // We don't queue power Irps, we'll only check if the // device was removed, otherwise we'll take appropriate // action and send it to the next lower driver. In general // drivers should not cause long delays while handling power // IRPs. If a driver cannot handle a power IRP in a brief time, // it should return STATUS_PENDING and queue all incoming // IRPs until the IRP completes. // if(Removed == deviceExtension->DeviceState) { // // Even if a driver fails the IRP, it must nevertheless call // PoStartNextPowerIrp to inform the Power Manager that it // is ready to handle another power IRP. // PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } if(NotStarted == deviceExtension->DeviceState) { // // if the device is not started yet, pass it down // PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); } BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPower::")); BulkUsb_IoIncrement(deviceExtension); switch(irpStack->MinorFunction) { case IRP_MN_SET_POWER: // // The Power Manager sends this IRP for one of the // following reasons: // 1) To notify drivers of a change to the system power state. // 2) To change the power state of a device for which // the Power Manager is performing idle detection. // A driver sends IRP_MN_SET_POWER to change the power // state of its device if it's a power policy owner for the // device. // IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceSetPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_QUERY_POWER: // // The Power Manager sends a power IRP with the minor // IRP code IRP_MN_QUERY_POWER to determine whether it // can safely change to the specified system power state // (S1-S5) and to allow drivers to prepare for such a change. // If a driver can put its device in the requested state, // it sets status to STATUS_SUCCESS and passes the IRP down. // IoMarkIrpPending(Irp); switch(irpStack->Parameters.Power.Type) { case SystemPowerState: HandleSystemQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; case DevicePowerState: HandleDeviceQueryPower(DeviceObject, Irp); ntStatus = STATUS_PENDING; break; } break; case IRP_MN_WAIT_WAKE: // // The minor power IRP code IRP_MN_WAIT_WAKE provides // for waking a device or waking the system. Drivers // of devices that can wake themselves or the system // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE // only to devices that always wake the system, such as // the power-on switch. // IoMarkIrpPending(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); PoStartNextPowerIrp(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("Lower drivers failed the wait-wake Irp")); } ntStatus = STATUS_PENDING; // // push back the count HERE and NOT in completion routine // a pending Wait Wake Irp should not impede stopping the device // BulkUsb_DbgPrint(3, ("IRP_MN_WAIT_WAKE::")); BulkUsb_IoDecrement(deviceExtension); break; case IRP_MN_POWER_SEQUENCE: // // A driver sends this IRP as an optimization to determine // whether its device actually entered a specific power state. // This IRP is optional. Power Manager cannot send this IRP. // default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("Lower drivers failed this Irp")); } BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPower::")); BulkUsb_IoDecrement(deviceExtension); break; } return ntStatus; }
VOID WaitWakeCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) /*++ Routine Description: This is the PoRequest completion routine for the wait wake irp. Arguments: DeviceObject - pointer to device object MinorFunction - irp minor function PowerState - power state of the irp. Context - context passed to the completion routine. IoStatus - status block. Return Value: None --*/ { NTSTATUS ntStatus; POWER_STATE powerState; PDEVICE_EXTENSION deviceExtension; BulkUsb_DbgPrint(3, ("WaitWakeCallback - begins\n")); deviceExtension = (PDEVICE_EXTENSION) Context; InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0); if(!NT_SUCCESS(IoStatus->Status)) { return; } // // wake up the device // if(deviceExtension->DevPower == PowerDeviceD0) { BulkUsb_DbgPrint(3, ("device already powered up...\n")); return; } BulkUsb_DbgPrint(3, ("WaitWakeCallback::")); BulkUsb_IoIncrement(deviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc, deviceExtension, NULL); if(deviceExtension->WaitWakeEnable) { IssueWaitWake(deviceExtension); } BulkUsb_DbgPrint(3, ("WaitWakeCallback - ends\n")); return; }
VOID HoldIoRequestsWorkerRoutine( IN PDEVICE_OBJECT DeviceObject, IN PVOID Context ) /*++ Routine Description: This routine waits for the I/O in progress to finish and then sends the device power irp (query/set) down the stack. Arguments: DeviceObject - pointer to device object Context - context passed to the work-item. Return Value: None --*/ { PIRP irp; NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PWORKER_THREAD_CONTEXT context; BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - begins\n")); // // initialize variables // deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; context = (PWORKER_THREAD_CONTEXT) Context; irp = (PIRP) context->Irp; // // wait for I/O in progress to finish. // the stop event is signalled when the counter drops to 1. // invoke BulkUsb_IoDecrement twice: once each for the S-Irp and D-Irp. // BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::")); BulkUsb_IoDecrement(deviceExtension); BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::")); BulkUsb_IoDecrement(deviceExtension); KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL); // // Increment twice to restore the count // BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::")); BulkUsb_IoIncrement(deviceExtension); BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::")); BulkUsb_IoIncrement(deviceExtension); // // now send the Irp down // IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("Lower driver fail a power Irp\n")); } IoFreeWorkItem(context->WorkItem); ExFreePool((PVOID)context); BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - ends\n")); }
VOID IdleNotificationCallback( IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: "A pointer to a callback function in your driver is passed down the stack with this IOCTL, and it is this callback function that is called by USBHUB when it safe for your device to power down." "When the callback in your driver is called, all you really need to do is to to first ensure that a WaitWake Irp has been submitted for your device, if remote wake is possible for your device and then request a SetD2 (or DeviceWake)" Arguments: DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; POWER_STATE powerState; KEVENT irpCompletionEvent; PIRP_COMPLETION_CONTEXT irpContext; BulkUsb_DbgPrint(3, ("IdleNotificationCallback - begins\n")); // // Dont idle, if the device was just disconnected or being stopped // i.e. return for the following DeviceState(s) // NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved, Removed // if(DeviceExtension->DeviceState != Working) { return; } // // If there is not already a WW IRP pending, submit one now // if(DeviceExtension->WaitWakeEnable) { IssueWaitWake(DeviceExtension); } // // power down the device // irpContext = (PIRP_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(IRP_COMPLETION_CONTEXT)); if(!irpContext) { BulkUsb_DbgPrint(1, ("Failed to alloc memory for irpContext\n")); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } else { // // increment the count. In the HoldIoRequestWorkerRoutine, the // count is decremented twice (one for the system Irp and the // other for the device Irp. An increment here compensates for // the sytem irp..The decrement corresponding to this increment // is in the completion function // BulkUsb_DbgPrint(3, ("IdleNotificationCallback::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = DeviceExtension->PowerDownLevel; KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE); irpContext->DeviceExtension = DeviceExtension; irpContext->Event = &irpCompletionEvent; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc, irpContext, NULL); if(STATUS_PENDING == ntStatus) { BulkUsb_DbgPrint(3, ("IdleNotificationCallback::" "waiting for the power irp to complete\n")); KeWaitForSingleObject(&irpCompletionEvent, Executive, KernelMode, FALSE, NULL); } } if(!NT_SUCCESS(ntStatus)) { if(irpContext) { ExFreePool(irpContext); } } BulkUsb_DbgPrint(3, ("IdleNotificationCallback - ends\n")); }
NTSTATUS BulkUsb_DispatchDevCtrl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Dispatch routine for IRP_MJ_DEVICE_CONTROL Arguments: DeviceObject - pointer to device object Irp - I/O request packet Return Value: NT status value --*/ { ULONG code; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG info; NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; // // initialize variables // info = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); code = irpStack->Parameters.DeviceIoControl.IoControlCode; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if(deviceExtension->DeviceState != Working) { BulkUsb_DbgPrint(1, ("Invalid device state\n")); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::")); BulkUsb_IoIncrement(deviceExtension); // // It is true that the client driver cancelled the selective suspend // request in the dispatch routine for create. // But there is no guarantee that it has indeed been completed. // so wait on the NoIdleReqPendEvent and proceed only if this event // is signalled. // BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n")); // // make sure that the selective suspend request has been completed. // if(deviceExtension->SSEnable) { KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL); } switch(code) { case IOCTL_BULKUSB_RESET_PIPE: { PFILE_OBJECT fileObject; PUSBD_PIPE_INFORMATION pipe; pipe = NULL; fileObject = NULL; // // FileObject is the address of the kernel file object to // which the IRP is directed. Drivers use the FileObject // to correlate IRPs in a queue. // fileObject = irpStack->FileObject; if(fileObject == NULL) { ntStatus = STATUS_INVALID_PARAMETER; break; } pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext; if(pipe == NULL) { ntStatus = STATUS_INVALID_PARAMETER; } else { ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe); } break; } case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR: { ULONG length; if(deviceExtension->UsbConfigurationDescriptor) { length = deviceExtension->UsbConfigurationDescriptor->wTotalLength; if(outputBufferLength >= length) { RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length); info = length; ntStatus = STATUS_SUCCESS; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } } else { ntStatus = STATUS_UNSUCCESSFUL; } break; } case IOCTL_BULKUSB_RESET_DEVICE: ntStatus = BulkUsb_ResetDevice(DeviceObject); break; default : ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
NTSTATUS IdleNotificationRequestComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension ) /*++ Routine Description: Completion routine for idle notification irp Arguments: DeviceObject - pointer to device object Irp - I/O request packet DeviceExtension - pointer to device extension Return Value: NT status value --*/ { NTSTATUS ntStatus; POWER_STATE powerState; KIRQL oldIrql; LARGE_INTEGER dueTime; PIRP idleIrp; PUSB_IDLE_CALLBACK_INFO idleCallbackInfo; BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - begins\n")); idleIrp = NULL; // // check the Irp status // ntStatus = Irp->IoStatus.Status; if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) { BulkUsb_DbgPrint(1, ("Idle irp completes with error::")); switch(ntStatus) { case STATUS_INVALID_DEVICE_REQUEST: BulkUsb_DbgPrint(1, ("STATUS_INVALID_DEVICE_REQUEST\n")); break; case STATUS_CANCELLED: BulkUsb_DbgPrint(1, ("STATUS_CANCELLED\n")); break; case STATUS_POWER_STATE_INVALID: BulkUsb_DbgPrint(1, ("STATUS_POWER_STATE_INVALID\n")); goto IdleNotificationRequestComplete_Exit; case STATUS_DEVICE_BUSY: BulkUsb_DbgPrint(1, ("STATUS_DEVICE_BUSY\n")); break; default: BulkUsb_DbgPrint(1, ("default: status = %X\n", ntStatus)); break; } // // if in error, issue a SetD0 // BulkUsb_DbgPrint(3, ("IdleNotificationRequestComplete::")); BulkUsb_IoIncrement(DeviceExtension); powerState.DeviceState = PowerDeviceD0; ntStatus = PoRequestPowerIrp( DeviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc, DeviceExtension, NULL); if(!NT_SUCCESS(ntStatus)) { BulkUsb_DbgPrint(1, ("PoRequestPowerIrp failed\n")); } } IdleNotificationRequestComplete_Exit: KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql); idleCallbackInfo = DeviceExtension->IdleCallbackInfo; DeviceExtension->IdleCallbackInfo = NULL; idleIrp = (PIRP) InterlockedExchangePointer( &DeviceExtension->PendingIdleIrp, NULL); InterlockedExchange(&DeviceExtension->IdleReqPend, 0); KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql); if(idleCallbackInfo) { ExFreePool(idleCallbackInfo); } // // since the irp was created using IoAllocateIrp, // the Irp needs to be freed using IoFreeIrp. // Also return STATUS_MORE_PROCESSING_REQUIRED so that // the kernel does not reference this in the near future. // if(idleIrp) { BulkUsb_DbgPrint(3, ("completion routine has a valid irp and frees it\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } else { // // The CancelSelectiveSuspend routine has grabbed the Irp from the device // extension. Now the last one to decrement the FreeIdleIrpCount should // free the irp. // if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) { BulkUsb_DbgPrint(3, ("completion routine frees the irp\n")); IoFreeIrp(Irp); KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE); } } if(DeviceExtension->SSEnable) { BulkUsb_DbgPrint(3, ("Set the timer to fire DPCs\n")); dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, // 5000 ms &DeviceExtension->DeferredProcCall); BulkUsb_DbgPrint(3, ("IdleNotificationRequestCompete - ends\n")); } return STATUS_MORE_PROCESSING_REQUIRED; }