Skip to content

Commit dd2f468

Browse files
committed
[USBSER] Implement UsbSerSetDevicePowerState().
1 parent f3c00b0 commit dd2f468

2 files changed

Lines changed: 341 additions & 4 deletions

File tree

drivers/usb/usbser/usbser.c

Lines changed: 338 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,15 +1674,276 @@ UsbSerCleanup(IN PDEVICE_OBJECT DeviceObject,
16741674
return STATUS_SUCCESS;
16751675
}
16761676

1677+
VOID
1678+
NTAPI
1679+
UsbSerPoRequestCompletion(IN PDEVICE_OBJECT DeviceObject,
1680+
IN UCHAR MinorFunction,
1681+
IN POWER_STATE PowerState,
1682+
IN PVOID Context,
1683+
IN PIO_STATUS_BLOCK IoStatus)
1684+
{
1685+
PDEVICE_OBJECT PhysicalDevice = Context;
1686+
PUSBSER_DEVICE_EXTENSION Extension;
1687+
PIRP Irp;
1688+
1689+
DPRINT1("UsbSerPoRequestCompletion: %p, %X\n", DeviceObject, MinorFunction);
1690+
1691+
Extension = PhysicalDevice->DeviceExtension;
1692+
Irp = Extension->SetPwrIrp;
1693+
1694+
IoCopyCurrentIrpStackLocationToNext(Irp);
1695+
PoStartNextPowerIrp(Irp);
1696+
PoCallDriver(Extension->LowerDevice, Irp);
1697+
1698+
Extension->SetPwrIrp = NULL;
1699+
}
1700+
1701+
VOID
1702+
NTAPI
1703+
UsbSerSendWaitWake(IN PUSBSER_DEVICE_EXTENSION Extension)
1704+
{
1705+
UNIMPLEMENTED_DBGBREAK();
1706+
}
1707+
1708+
BOOLEAN
1709+
NTAPI
1710+
UsbSerSetDevicePowerState(IN PDEVICE_OBJECT DeviceObject,
1711+
IN POWER_STATE State)
1712+
{
1713+
PUSBSER_DEVICE_EXTENSION Extension;
1714+
KIRQL Irql;
1715+
BOOLEAN Result;
1716+
1717+
DPRINT1("UsbSerSetDevicePowerState: %p\n", DeviceObject);
1718+
1719+
Extension = DeviceObject->DeviceExtension;
1720+
1721+
if (State.DeviceState == PowerDeviceD0)
1722+
{
1723+
DPRINT1("PowerDeviceD0\n");
1724+
Result = TRUE;
1725+
}
1726+
else if (State.DeviceState == PowerDeviceD1)
1727+
{
1728+
DPRINT1("PowerDeviceD1\n");
1729+
1730+
KeAcquireSpinLock(&Extension->SpinLock, &Irql);
1731+
Extension->DevicePowerState = State.DeviceState;
1732+
KeReleaseSpinLock(&Extension->SpinLock, Irql);
1733+
1734+
UsbSerAbortPipes(DeviceObject);
1735+
1736+
if (Extension->IsWaitWake && State.DeviceState <= Extension->DeviceWake)
1737+
UsbSerSendWaitWake(Extension);
1738+
1739+
Result = FALSE;
1740+
}
1741+
else if (State.DeviceState == PowerDeviceD2)
1742+
{
1743+
DPRINT1("PowerDeviceD2\n");
1744+
1745+
KeAcquireSpinLock(&Extension->SpinLock, &Irql);
1746+
Extension->DevicePowerState = State.DeviceState;
1747+
KeReleaseSpinLock(&Extension->SpinLock, Irql);
1748+
1749+
UsbSerAbortPipes(DeviceObject);
1750+
1751+
if (Extension->IsWaitWake && State.DeviceState <= Extension->DeviceWake)
1752+
UsbSerSendWaitWake(Extension);
1753+
1754+
Result = FALSE;
1755+
}
1756+
else if (State.DeviceState == PowerDeviceD3)
1757+
{
1758+
DPRINT1("PowerDeviceD3\n");
1759+
1760+
KeAcquireSpinLock(&Extension->SpinLock, &Irql);
1761+
Extension->DevicePowerState = State.DeviceState;
1762+
KeReleaseSpinLock(&Extension->SpinLock, Irql);
1763+
1764+
UsbSerAbortPipes(DeviceObject);
1765+
1766+
Result = FALSE;
1767+
}
1768+
else
1769+
{
1770+
DPRINT1("UsbSerSetDevicePowerState: DeviceState %X\n", State.DeviceState);
1771+
Result = FALSE;
1772+
}
1773+
1774+
PoSetPowerState(DeviceObject, DevicePowerState, State);
1775+
1776+
return Result;
1777+
}
1778+
1779+
NTSTATUS
1780+
NTAPI
1781+
UsbSerWaitWakeIrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
1782+
IN PIRP Irp,
1783+
IN PVOID Context)
1784+
{
1785+
UNIMPLEMENTED_DBGBREAK();
1786+
return STATUS_MORE_PROCESSING_REQUIRED;
1787+
}
1788+
1789+
NTSTATUS
1790+
NTAPI
1791+
UsbSerPowerIrpComplete(IN PDEVICE_OBJECT DeviceObject,
1792+
IN PIRP Irp,
1793+
IN PVOID Context)
1794+
{
1795+
UNIMPLEMENTED_DBGBREAK();
1796+
return STATUS_MORE_PROCESSING_REQUIRED;
1797+
}
1798+
16771799
NTSTATUS
16781800
NTAPI
16791801
UsbSerProcessPowerIrp(IN PDEVICE_OBJECT DeviceObject,
16801802
IN PIRP Irp)
16811803
{
1682-
DPRINT("UsbSerProcessPowerIrp: DeviceObject %p, Irp %p\n", DeviceObject, Irp);
1683-
PAGED_CODE();
1684-
UNIMPLEMENTED;
1685-
return STATUS_NOT_IMPLEMENTED;
1804+
PUSBSER_DEVICE_EXTENSION Extension;
1805+
PIO_STACK_LOCATION IoStack;
1806+
SYSTEM_POWER_STATE SystemState;
1807+
POWER_STATE DesiredDevicePowerState;
1808+
ULONG ix;
1809+
BOOLEAN Result;
1810+
NTSTATUS Status = STATUS_SUCCESS;
1811+
1812+
DPRINT1("UsbSerProcessPowerIrp: %p, %p\n", DeviceObject, Irp);
1813+
1814+
Extension = DeviceObject->DeviceExtension;
1815+
IoStack = IoGetCurrentIrpStackLocation(Irp);
1816+
1817+
if (IoStack->MinorFunction == IRP_MN_WAIT_WAKE)
1818+
{
1819+
Extension->MinDeviceState = Extension->DeviceWake;
1820+
1821+
DPRINT1("UsbSerProcessPowerIrp: IRP_MN_WAIT_WAKE (%X, %X)\n", Extension->DevicePowerState, Extension->DeviceWake);
1822+
1823+
if (Extension->DevicePowerState != PowerDeviceD0 && Extension->DeviceWake <= Extension->DevicePowerState)
1824+
{
1825+
IoCopyCurrentIrpStackLocationToNext(Irp);
1826+
IoSetCompletionRoutine(Irp, UsbSerWaitWakeIrpCompletionRoutine, DeviceObject, TRUE, TRUE, TRUE);
1827+
1828+
DPRINT1("UsbSerProcessPowerIrp: Send down wait wake\n");
1829+
1830+
PoStartNextPowerIrp(Irp);
1831+
PoCallDriver(Extension->LowerDevice, Irp);
1832+
Status = STATUS_PENDING;
1833+
}
1834+
else
1835+
{
1836+
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
1837+
PoStartNextPowerIrp(Irp);
1838+
IoCompleteRequest(Irp, 0);
1839+
Status = STATUS_INVALID_DEVICE_STATE;
1840+
}
1841+
}
1842+
else if (IoStack->MinorFunction == IRP_MN_POWER_SEQUENCE)
1843+
{
1844+
DPRINT1("UsbSerProcessPowerIrp: IRP_MN_POWER_SEQUENCE\n");
1845+
1846+
IoCopyCurrentIrpStackLocationToNext(Irp);
1847+
PoStartNextPowerIrp(Irp);
1848+
Status = PoCallDriver(Extension->LowerDevice, Irp);
1849+
}
1850+
else if (IoStack->MinorFunction == IRP_MN_SET_POWER)
1851+
{
1852+
DPRINT1("UsbSerProcessPowerIrp: IRP_MN_SET_POWER\n");
1853+
1854+
if (IoStack->Parameters.Power.Type == SystemPowerState)
1855+
{
1856+
DPRINT1("UsbSerProcessPowerIrp: SystemPowerState\n");
1857+
1858+
SystemState = IoStack->Parameters.Power.State.SystemState;
1859+
DPRINT1("UsbSerProcessPowerIrp: SystemState %X\n", SystemState);
1860+
1861+
for (ix = 0; ix < 8; ix++)
1862+
{
1863+
DPRINT1("UsbSerProcessPowerIrp: DeviceState[%X] %X\n", ix, Extension->Capabilities.DeviceState[ix]);
1864+
}
1865+
1866+
DPRINT1("UsbSerProcessPowerIrp: DeviceWake %X SystemWake %X\n",
1867+
Extension->Capabilities.DeviceWake, Extension->Capabilities.SystemWake);
1868+
1869+
if (SystemState == PowerSystemWorking)
1870+
{
1871+
DPRINT1("UsbSerProcessPowerIrp: Setting to D0\n");
1872+
DesiredDevicePowerState.DeviceState = PowerDeviceD0;
1873+
}
1874+
else if (Extension->IsWaitWake)
1875+
{
1876+
DPRINT1("UsbSerProcessPowerIrp: We want to send a wait wake Irp\n");
1877+
DesiredDevicePowerState.DeviceState = Extension->Capabilities.DeviceState[SystemState];
1878+
}
1879+
else
1880+
{
1881+
DPRINT1("UsbSerProcessPowerIrp: No wait wake Irp to send\n");
1882+
DesiredDevicePowerState.DeviceState = PowerDeviceD3;
1883+
}
1884+
1885+
DPRINT1("UsbSerProcessPowerIrp: DesiredDevicePowerState %X\n", DesiredDevicePowerState.SystemState);
1886+
1887+
if (DesiredDevicePowerState.DeviceState != Extension->DevicePowerState)
1888+
{
1889+
Extension->SetPwrIrp = Irp;
1890+
Status = PoRequestPowerIrp(Extension->PhysicalDevice,
1891+
IRP_MN_SET_POWER,
1892+
DesiredDevicePowerState,
1893+
UsbSerPoRequestCompletion,
1894+
DeviceObject,
1895+
NULL);
1896+
}
1897+
else
1898+
{
1899+
IoCopyCurrentIrpStackLocationToNext(Irp);
1900+
PoStartNextPowerIrp(Irp);
1901+
Status = PoCallDriver(Extension->LowerDevice, Irp);
1902+
}
1903+
}
1904+
else if (IoStack->Parameters.Power.Type == DevicePowerState)
1905+
{
1906+
DPRINT1("UsbSerProcessPowerIrp: DevicePowerState\n");
1907+
1908+
Result = UsbSerSetDevicePowerState(DeviceObject, IoStack->Parameters.Power.State);
1909+
1910+
IoCopyCurrentIrpStackLocationToNext(Irp);
1911+
1912+
if (Result)
1913+
IoSetCompletionRoutine(Irp, UsbSerPowerIrpComplete, DeviceObject, TRUE, TRUE, TRUE);
1914+
1915+
PoStartNextPowerIrp(Irp);
1916+
Status = PoCallDriver(Extension->LowerDevice, Irp);
1917+
}
1918+
}
1919+
else if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
1920+
{
1921+
DPRINT1("UsbSerProcessPowerIrp: IRP_MN_QUERY_POWER\n");
1922+
1923+
if (Extension->IsWaitWake &&
1924+
IoStack->Parameters.Power.Type == SystemPowerState &&
1925+
Extension->Capabilities.DeviceState[IoStack->Parameters.Power.State.DeviceState] > Extension->DeviceWake)
1926+
{
1927+
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
1928+
Status = STATUS_INVALID_DEVICE_STATE;
1929+
PoStartNextPowerIrp(Irp);
1930+
IoCompleteRequest(Irp, 0);
1931+
}
1932+
else
1933+
{
1934+
IoCopyCurrentIrpStackLocationToNext(Irp);
1935+
PoStartNextPowerIrp(Irp);
1936+
Status = PoCallDriver(Extension->LowerDevice, Irp);
1937+
}
1938+
}
1939+
else
1940+
{
1941+
IoCopyCurrentIrpStackLocationToNext(Irp);
1942+
PoStartNextPowerIrp(Irp);
1943+
Status = PoCallDriver(Extension->LowerDevice, Irp);
1944+
}
1945+
1946+
return Status;
16861947
}
16871948

16881949
NTSTATUS
@@ -1747,6 +2008,68 @@ UsbSerUnload(IN PDRIVER_OBJECT DriverObject)
17472008
PAGED_CODE();
17482009
}
17492010

2011+
NTSTATUS
2012+
NTAPI
2013+
UsbSerIrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
2014+
IN PIRP Irp,
2015+
IN PVOID Context)
2016+
{
2017+
PRKEVENT Event = Context;
2018+
2019+
DPRINT("UsbSerIrpCompletionRoutine: Irp %p\n", Irp);
2020+
2021+
KeSetEvent(Event, EVENT_INCREMENT, FALSE);
2022+
2023+
return STATUS_MORE_PROCESSING_REQUIRED;
2024+
}
2025+
2026+
NTSTATUS
2027+
NTAPI
2028+
UsbSerQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
2029+
IN PDEVICE_CAPABILITIES Capabilities)
2030+
{
2031+
PIO_STACK_LOCATION IoStack;
2032+
KEVENT Event;
2033+
PIRP Irp;
2034+
NTSTATUS Status;
2035+
2036+
DPRINT("UsbSerQueryCapabilities\n");
2037+
2038+
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
2039+
if (!Irp)
2040+
{
2041+
DPRINT1("UsbSerQueryCapabilities: failed allocate irp\n");
2042+
return STATUS_INSUFFICIENT_RESOURCES;
2043+
}
2044+
2045+
IoStack = IoGetNextIrpStackLocation(Irp);
2046+
IoStack->MajorFunction = IRP_MJ_PNP;
2047+
IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
2048+
2049+
KeInitializeEvent(&Event, NotificationEvent, FALSE);
2050+
2051+
IoSetCompletionRoutine(Irp, UsbSerIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
2052+
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
2053+
2054+
RtlZeroMemory(Capabilities, sizeof(*Capabilities));
2055+
2056+
Capabilities->Size = sizeof(*Capabilities);
2057+
Capabilities->Version = 1;
2058+
Capabilities->SurpriseRemovalOK = 1;
2059+
Capabilities->Address = 0xFFFFFFFF;
2060+
Capabilities->UINumber = 0xFFFFFFFF;
2061+
2062+
IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
2063+
2064+
Status = IoCallDriver(DeviceObject, Irp);
2065+
if (Status == STATUS_PENDING)
2066+
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
2067+
2068+
IoFreeIrp(Irp);
2069+
2070+
return Status;
2071+
}
2072+
17502073
NTSTATUS
17512074
NTAPI
17522075
UsbSerPnPAddDevice(IN PDRIVER_OBJECT DriverObject,
@@ -1762,6 +2085,7 @@ UsbSerPnPAddDevice(IN PDRIVER_OBJECT DriverObject,
17622085
WCHAR CharSymLink[64];
17632086
UNICODE_STRING SymLinkName;
17642087
ULONG ExtSize;
2088+
ULONG ix;
17652089

17662090
PAGED_CODE();
17672091
DPRINT("UsbSerPnPAddDevice: DriverObject %p, TargetDevice %p\n", DriverObject, TargetDevice);
@@ -1872,6 +2196,16 @@ UsbSerPnPAddDevice(IN PDRIVER_OBJECT DriverObject,
18722196
NewDevice->Flags |= DO_POWER_PAGABLE;
18732197
NewDevice->Flags &= ~DO_DEVICE_INITIALIZING;
18742198

2199+
UsbSerQueryCapabilities(Extension->LowerDevice, &Extension->Capabilities);
2200+
2201+
Extension->MinDeviceState = 0;
2202+
2203+
for (ix = 2; ix < 5; ix++)
2204+
{
2205+
if (Extension->Capabilities.DeviceState[ix] < PowerDeviceD3)
2206+
Extension->MinDeviceState = Extension->Capabilities.DeviceState[ix];
2207+
}
2208+
18752209
Extension->WmiLibInfo.GuidCount = 1;
18762210
Extension->WmiLibInfo.GuidList = SerialWmiGuidList;
18772211

drivers/usb/usbser/usbser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ typedef struct _USBSER_DEVICE_EXTENSION
143143
DEVICE_POWER_STATE DeviceWake;
144144
PIRP WakeIrp;
145145
LONG OpenCount;
146+
DEVICE_CAPABILITIES Capabilities;
146147
DEVICE_POWER_STATE DevicePowerState;
148+
DEVICE_POWER_STATE MinDeviceState;
149+
PIRP SetPwrIrp;
147150
PIRP CurrentReadIrp;
148151
LIST_ENTRY ReadQueueList;
149152
ULONG ReadLength;

0 commit comments

Comments
 (0)