NTSTATUS NTAPI HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n")); // initialize variables deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n" "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n", systemState - 1, deviceExtension->SysPower - 1)); // Fail a query for a power state incompatible with waking up the system if ((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake)) { FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n")); PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::")); FreeBT_IoDecrement(deviceExtension); return ntStatus; } // if querying for a lower S-state, issue a wait-wake if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable)) { IssueWaitWake(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n")); return STATUS_PENDING; }
VOID NTAPI WaitWakeCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus) { NTSTATUS ntStatus; POWER_STATE powerState; PDEVICE_EXTENSION deviceExtension; FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n")); deviceExtension = (PDEVICE_EXTENSION) Context; InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0); if(!NT_SUCCESS(IoStatus->Status)) { return; } // wake up the device if(deviceExtension->DevPower == PowerDeviceD0) { FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n")); return; } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::")); FreeBT_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); } FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n")); return; }
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 HandleSystemQueryPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine handles the irp with minor function of type IRP_MN_QUERY_POWER for the system power states. Arguments: DeviceObject - pointer to device object Irp - I/O request packet sent by the power manager. Return Value: NT status value --*/ { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; MobiUsb_DbgPrint(3, ("file mobipwr: HandleSystemQueryPower - begins\n")); // // initialize variables // deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; MobiUsb_DbgPrint(3, ("file mobipwr: Query for system power state S%X\n" "Current system power state S%X\n", systemState - 1, deviceExtension->SysPower - 1)); // // if querying for a lower S-state, issue a wait-wake // if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable)) { IssueWaitWake(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); MobiUsb_DbgPrint(3, ("file mobipwr: HandleSystemQueryPower - ends\n")); return STATUS_PENDING; }
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; MobiUsb_DbgPrint(3, ("file mobipwr: 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) { MobiUsb_DbgPrint(3, ("file mobipwr: device already powered up...\n")); return; } MobiUsb_DbgPrint(3, ("file mobipwr: WaitWakeCallback::")); MobiUsb_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); } MobiUsb_DbgPrint(3, ("file mobipwr: WaitWakeCallback - ends\n")); return; }
NTSTATUS HandleSystemQueryPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine handles the irp with minor function of type IRP_MN_QUERY_POWER for the system power states. Arguments: DeviceObject - pointer to device object Irp - I/O request packet sent by the power manager. Return Value: NT status value --*/ { NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; SYSTEM_POWER_STATE systemState; PIO_STACK_LOCATION irpStack; BulkUsb_DbgPrint(3, ("HandleSystemQueryPower - begins\n")); // // initialize variables // deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); systemState = irpStack->Parameters.Power.State.SystemState; BulkUsb_DbgPrint(3, ("Query for system power state S%X\n" "Current system power state S%X\n", systemState - 1, deviceExtension->SysPower - 1)); // // Fail a query for a power state incompatible with waking up the system // if((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake)) { BulkUsb_DbgPrint(1, ("Query for an incompatible system power state\n")); PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("HandleSystemQueryPower::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; } // // if querying for a lower S-state, issue a wait-wake // if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable)) { IssueWaitWake(deviceExtension); } IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine, deviceExtension, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp); BulkUsb_DbgPrint(3, ("HandleSystemQueryPower - ends\n")); return STATUS_PENDING; }
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")); }