ReactOS 0.4.17-dev-1281-g065abb3
childpdo.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS SuperSpeed USB Hub Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Child PDO: creation, PnP and power, query interfaces and the client IOCTL front end
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9#include "devhcd.h"
10
11#define NDEBUG
12#include <debug.h>
13
14/* GLOBALS ********************************************************************/
15
16/* Reference tag on the device object held by its PDO; only the address matters */
17static const char HubTagPdo[] = "hub child pdo";
18
19/* Time the device gets to find a driver before the device machine suspends it */
20#define HUB_PDO_DRIVER_WAIT_TIME 10000
21
22/* Last valid URB function and the undocumented ones below it */
23#define HUB_URB_FUNCTION_LAST 0x003C
24#define HUB_URB_FUNCTION_FAST_PATH_1 0x0039
25#define HUB_URB_FUNCTION_FAST_PATH_2 0x003A
26#define HUB_URB_FUNCTION_SELECT_LIKE 0x003B
27
28/* MS OS 2.0 descriptor set index of GET_MS_FEATURE_DESCRIPTOR */
29#define HUB_MSOS20_SET_INDEX 7
30
31/* Device IOCTLs passed to UCX with the device handle stamped in */
32#define HUB_USB_BUFFERED_IOCTL(Function) \
33 CTL_CODE(FILE_DEVICE_USB, Function, METHOD_BUFFERED, FILE_ANY_ACCESS)
34
35#define HUB_IOCTL_GET_TRANSPORT_CHARACTERISTICS HUB_USB_BUFFERED_IOCTL(USB_GET_TRANSPORT_CHARACTERISTICS)
36#define HUB_IOCTL_REGISTER_TRANSPORT_CHANGE HUB_USB_BUFFERED_IOCTL(USB_REGISTER_FOR_TRANSPORT_CHARACTERISTICS_CHANGE)
37#define HUB_IOCTL_NOTIFY_TRANSPORT_CHANGE HUB_USB_BUFFERED_IOCTL(USB_NOTIFY_ON_TRANSPORT_CHARACTERISTICS_CHANGE)
38#define HUB_IOCTL_UNREGISTER_TRANSPORT_CHANGE HUB_USB_BUFFERED_IOCTL(USB_UNREGISTER_FOR_TRANSPORT_CHARACTERISTICS_CHANGE)
39#define HUB_IOCTL_START_TIME_SYNC HUB_USB_BUFFERED_IOCTL(USB_START_TRACKING_FOR_TIME_SYNC)
40#define HUB_IOCTL_GET_TIME_SYNC HUB_USB_BUFFERED_IOCTL(USB_GET_FRAME_NUMBER_AND_QPC_FOR_TIME_SYNC)
41#define HUB_IOCTL_STOP_TIME_SYNC HUB_USB_BUFFERED_IOCTL(USB_STOP_TRACKING_FOR_TIME_SYNC)
42#define HUB_IOCTL_GET_DEVICE_CHARACTERISTICS HUB_USB_BUFFERED_IOCTL(USB_GET_DEVICE_CHARACTERISTICS)
43
44/* Payload sizes of the two stamped IOCTLs; both are 1-byte packed with the handle at offset 4 */
45#define HUB_TRANSPORT_REGISTRATION_SIZE (sizeof(ULONG) + sizeof(PVOID) + 24)
46#define HUB_DEVICE_CHARACTERISTICS_SIZE 0x18
47#define HUB_STAMPED_HANDLE_OFFSET 4
48
49/* User mode IOCTLs that reach the PDO queue */
50#define HUB_IOCTL_MEDIA_SERIAL_NUMBER CTL_CODE(FILE_DEVICE_MASS_STORAGE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS)
51
52/* RECORD_FAILURE copies at most this much client data */
53#define HUB_START_FAIL_MAX 4096
54
55/* Header of USB_START_FAILDATA, which usbioctl.h hides behind USB20_API */
57{
63};
64
65/* Billboard property payload: a 4 byte header, then one entry per alternate mode */
67{
72};
73
75{
80};
81
84
85/* Context of the work item that completes a device power IRP */
87{
89};
90
92
93/* {4D36E97E-E325-11CE-BFC1-08002BE10318} */
94static const GUID HubClassUnknown =
95 { 0x4d36e97e, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
96
97/* Device connection speed capabilities without a public name */
99 { 0xcde43191, 0x1fad, 0x4120, { 0xa7, 0xab, 0x74, 0x09, 0x56, 0xc6, 0x6f, 0x37 } };
101 { 0xad6f2a13, 0xc4d1, 0x4925, { 0x83, 0xcc, 0x96, 0x85, 0x7a, 0x24, 0x31, 0xd9 } };
102
103/* Device properties the PDO publishes */
105 { { 0xb1049018, 0x6da0, 0x4490, { 0xb0, 0xc9, 0x1e, 0x91, 0xf1, 0xf5, 0x5b, 0xd7 } }, 2 };
107 { { 0x32d615be, 0x32f4, 0x4fdc, { 0xbc, 0x48, 0xfc, 0x54, 0x30, 0x1a, 0xb6, 0xc4 } }, 2 };
109 { { 0xb5a825b8, 0x3907, 0x40b5, { 0xab, 0xca, 0x84, 0x51, 0xe2, 0x45, 0x3d, 0x5f } }, 3 };
110
111/* LPM power settings; slots 0 to 3 differ for hubs, slot 4 is shared */
113{
114 { 0xfb093825, 0xbf59, 0x4fe6, { 0x8b, 0x6f, 0xaf, 0xd6, 0x71, 0x4c, 0x69, 0xe5 } },
115 { 0x903281ea, 0xc859, 0x47a9, { 0x89, 0x01, 0x7a, 0x11, 0x8c, 0x7b, 0xf5, 0xa7 } },
116 { 0xa7b5d35e, 0xc12c, 0x4f36, { 0xa4, 0x4f, 0x00, 0x62, 0x8f, 0x90, 0x03, 0x88 } },
117 { 0x300c0440, 0xee77, 0x4c1b, { 0xaf, 0x99, 0x3a, 0x33, 0xf8, 0xa9, 0xca, 0x5d } },
118 { 0xd4e98f31, 0x5ffe, 0x4ce1, { 0xbe, 0x31, 0x1b, 0x38, 0xb3, 0x84, 0xc0, 0x09 } }
119};
120
122{
123 { 0xc5f91e9d, 0x0ced, 0x43f2, { 0x90, 0x5e, 0x8f, 0x9d, 0x38, 0xe9, 0x33, 0x39 } },
124 { 0x34751a37, 0xe607, 0x452a, { 0xb9, 0xf7, 0xd0, 0x20, 0xfc, 0x5c, 0xd0, 0xdc } },
125 { 0x329423dd, 0x222f, 0x4b04, { 0x81, 0x5b, 0x08, 0xc1, 0xa6, 0xd8, 0x9c, 0x8e } },
126 { 0xbbfbadaf, 0x7520, 0x491a, { 0x91, 0x0d, 0x4a, 0x2c, 0xee, 0x72, 0x20, 0x3f } },
127 { 0xd4e98f31, 0x5ffe, 0x4ce1, { 0xbe, 0x31, 0x1b, 0x38, 0xb3, 0x84, 0xc0, 0x09 } }
128};
129
131{
138
139#define HUB_LPM_POLICY_LINK_BITS (HUB_LPM_POLICY_U1_ENABLED | HUB_LPM_POLICY_U2_ENABLED | \
140 HUB_LPM_POLICY_U1_ACCEPT | HUB_LPM_POLICY_U2_ACCEPT | \
141 HUB_LPM_POLICY_U1_INITIATE | HUB_LPM_POLICY_U2_INITIATE)
142
143/* PoSetSystemWakeDevice is not exported everywhere; resolved at the first PDO creation */
144typedef
148
151
152static EVT_WDF_DEVICE_D0_ENTRY HubPdoEvtD0Entry;
153static EVT_WDF_DEVICE_D0_EXIT HubPdoEvtD0Exit;
154static EVT_WDF_DEVICE_PREPARE_HARDWARE HubPdoEvtPrepareHardware;
155static EVT_WDF_DEVICE_RELEASE_HARDWARE HubPdoEvtReleaseHardware;
156static EVT_WDF_DEVICE_SURPRISE_REMOVAL HubPdoEvtSurpriseRemoval;
157static EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT HubPdoEvtSelfManagedIoStart;
158static EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND HubPdoEvtSelfManagedIoSuspend;
159static EVT_WDF_DEVICE_QUERY_STOP HubPdoEvtQueryStop;
160static EVT_WDF_DEVICE_QUERY_REMOVE HubPdoEvtQueryRemove;
161static EVT_WDF_DEVICE_ENABLE_WAKE_AT_BUS HubPdoEvtEnableWakeAtBus;
162static EVT_WDF_DEVICE_DISABLE_WAKE_AT_BUS HubPdoEvtDisableWakeAtBus;
163static EVT_WDF_DEVICE_REPORTED_MISSING HubPdoEvtReportedMissing;
164static EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY HubPdoEvtResourceRequirementsQuery;
165static EVT_WDF_OBJECT_CONTEXT_CLEANUP HubPdoEvtCleanup;
166static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessInternalIoctl;
167static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessIoctl;
168static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessPnp;
169static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessSetPower;
170static EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST HubPdoEvtParentInterfaceQuery;
171static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL HubPdoEvtIoInternalDeviceControl;
172static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL HubPdoEvtIoDeviceControl;
173static EVT_WDF_WORKITEM HubPdoEvtCompletePowerIrp;
174static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubPdoWakeNotificationComplete;
175static POWER_SETTING_CALLBACK HubPdoLpmSettingChanged;
176
177/* FUNCTIONS ******************************************************************/
178
179HubPdo*
181 _In_ WDFDEVICE Device)
182{
183 return HubGetPdoContext(Device);
184}
185
186/* Status mappings */
187
189NTAPI
192{
193 switch (Status)
194 {
195 case STATUS_SUCCESS:
196 return USBD_STATUS_SUCCESS;
197
198 /* The first one is the hub's own addition to the shared table */
202
205
208
209 case STATUS_CANCELLED:
211
212 default:
214 }
215}
216
217static
219NTAPI
222{
223 switch (Status)
224 {
227 return STATUS_SUCCESS;
228
231
237
240
243
245 return STATUS_CANCELLED;
246
247 default:
248 return STATUS_UNSUCCESSFUL;
249 }
250}
251
252/* Small helpers */
253
256NTAPI
261{
262 PAGED_CODE();
263
264 KeClearEvent(&Child->m_PnpEvent);
265 Child->Post(Event);
266 HubWaitForPnpEvent(&Child->m_PnpEvent, What, Child->m_Object);
267 return Child->m_PnpStatus;
268}
269
271static
272VOID
273NTAPI
276{
277 PAGED_CODE();
278
279 KeClearEvent(&Child->m_PreStartEvent);
281 HubWaitForPnpEvent(&Child->m_PreStartEvent, "PdoPreStart", Child->m_Object);
282}
283
284static
286NTAPI
290{
291 Irp->IoStatus.Status = Status;
293 return Status;
294}
295
297static
299NTAPI
302{
303 NTSTATUS Status = Irp->IoStatus.Status;
304
306 return Status;
307}
308
309static
311NTAPI
313 _In_ WDFDEVICE Device,
315{
318}
319
320/* A placeholder has no controller target; it only gets here through the gate exemptions */
321static
323NTAPI
325 _In_ HubPdo* Pdo,
327{
328 if (Pdo->m_ControllerTarget == NULL)
329 {
330 DPRINT1("Port %u has no controller target for IRP %p\n", Pdo->m_PortNumber, Irp);
332 }
333
335 return IoCallDriver(Pdo->m_ControllerTarget, Irp);
336}
337
338static
340NTAPI
343 _In_ PIRP Irp,
344 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
345{
348
351}
352
355static
356VOID
357NTAPI
358HubPdoDispatchAndWait(
359 _In_ WDFDEVICE Device,
361{
363
367
370}
371
372/* Billboard and dual role properties */
373
375static
376VOID
377NTAPI
378HubPdoPublishBillboard(
379 _In_ HubPdo* Pdo)
380{
381 PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR Descriptor = Pdo->m_Child->m_Billboard->Descriptor;
382 ULONG Count = Descriptor->bNumberOfAlternateModes;
383 ULONG Size = sizeof(HubBillboardHeader) + Count * sizeof(HubBillboardMode);
386 ULONG Index;
387 ULONG Bit;
389
390 PAGED_CODE();
391
393 if (Header == NULL)
394 {
395 DPRINT1("No memory for the billboard property\n");
396 return;
397 }
398
399 Header->NumberOfAlternateModes = (UCHAR)Count;
400 Header->PreferredModeEntry = Descriptor->bPreferredAlternateMode;
401
402 /* Two bmConfigured bits per mode, the even bit is the low one */
403 Modes = (HubBillboardMode*)(Header + 1);
404 for (Index = 0; Index < Count; Index++)
405 {
406 Bit = Index * 2;
407 Modes[Index].SVid = Descriptor->AlternateMode[Index].wSVID;
408 Modes[Index].Mode = Descriptor->AlternateMode[Index].bAlternateMode;
409 Modes[Index].Status = (Descriptor->bmConfigured[Bit / 8] >> (Bit % 8)) & 3;
410 }
411
412 Status = IoSetDevicePropertyData(WdfDeviceWdmGetDeviceObject(Pdo->m_Device),
415 0,
417 Size,
418 Header);
419 if (!NT_SUCCESS(Status))
420 DPRINT1("Billboard property failed 0x%lx\n", Status);
421
423}
424
426static
427VOID
428NTAPI
429HubPdoReleaseBillboard(
430 _In_ HubPdo* Pdo)
431{
432 HubChild* Child = Pdo->m_Child;
433
434 PAGED_CODE();
435
436 if (Child->m_Billboard == NULL)
437 return;
438
439 IoSetDevicePropertyData(WdfDeviceWdmGetDeviceObject(Pdo->m_Device),
442 0,
444 0,
445 NULL);
446
448}
449
451static
452VOID
453NTAPI
454HubPdoPublishDualRole(
455 _In_ HubPdo* Pdo)
456{
457 ULONG Features = Pdo->m_Child->m_DualRolePartnerFeatures;
459
460 PAGED_CODE();
461
462 Status = IoSetDevicePropertyData(WdfDeviceWdmGetDeviceObject(Pdo->m_Device),
465 0,
467 sizeof(Features),
468 &Features);
469 if (!NT_SUCCESS(Status))
470 DPRINT1("Dual role property failed 0x%lx\n", Status);
471}
472
473/* A root port device publishes its own tunnel state, others the one their hub got. QUIRK: written once per enumeration */
475static
476VOID
477NTAPI
478HubPdoPublishTunnelState(
479 _In_ HubPdo* Pdo)
480{
481 HubFdo* Hub = Pdo->m_Hub;
482 ULONG State;
484
485 PAGED_CODE();
486
487 State = Hub->IsRootHub() ? Pdo->m_Child->m_TunnelState : Hub->m_Parent.TunnelState;
488 if (State < HUB_TUNNEL_STATE_NOT_USB4 || State > HUB_TUNNEL_STATE_UNKNOWN)
489 {
490 DPRINT1("Port %u has no valid USB4 tunnel state (%lu)\n", Pdo->m_PortNumber, State);
491 return;
492 }
493
494 Status = IoSetDevicePropertyData(WdfDeviceWdmGetDeviceObject(Pdo->m_Device),
497 0,
499 sizeof(State),
500 &State);
501 if (!NT_SUCCESS(Status))
502 DPRINT1("Port %u USB4 tunnel state property failed 0x%lx\n", Pdo->m_PortNumber, Status);
503}
504
505/* D3cold support interface handed to the function driver */
506
507static
508VOID
509NTAPI
512{
514
515 if (Pdo->m_AcpiD3Cold.InterfaceReference != NULL)
516 Pdo->m_AcpiD3Cold.InterfaceReference(Pdo->m_AcpiD3Cold.Context);
517}
518
519static
520VOID
521NTAPI
524{
526
527 if (Pdo->m_AcpiD3Cold.InterfaceDereference != NULL)
528 Pdo->m_AcpiD3Cold.InterfaceDereference(Pdo->m_AcpiD3Cold.Context);
529}
530
532static
533VOID
534NTAPI
535HubD3ColdSetSupport(
536 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context,
538{
540
541 if (Pdo->m_AcpiD3Cold.SetD3ColdSupport != NULL)
542 Pdo->m_AcpiD3Cold.SetD3ColdSupport(Pdo->m_AcpiD3Cold.Context, D3ColdSupport);
543
545 Pdo->m_Child->SetState(ChildState::D3ColdEnabledByDriver);
546 else
548}
549
551static
553NTAPI
554HubD3ColdGetIdleWakeInfo(
555 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context,
558{
560 HubChild* Child = Pdo->m_Child;
562
564
565 if (Pdo->m_AcpiD3Cold.GetIdleWakeInfo != NULL)
566 {
567 Status = Pdo->m_AcpiD3Cold.GetIdleWakeInfo(Pdo->m_AcpiD3Cold.Context,
570 if (NT_SUCCESS(Status))
571 return Status;
572 }
573
574 if (Pdo->m_Hub->m_Capabilities.SystemWake >= SystemPowerState &&
575 (Child->HasProperty(ChildProperty::RemoteWakeCapable) || Child->HasProperty(ChildProperty::IsHub)))
576 {
578 }
579 else
580 {
582 }
583
585}
586
588static
590NTAPI
591HubD3ColdGetCapability(
592 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context,
594{
597
598 PAGED_CODE();
599
600 if (Pdo->m_AcpiD3Cold.GetD3ColdCapability == NULL)
601 {
603 return STATUS_SUCCESS;
604 }
605
606 Status = Pdo->m_AcpiD3Cold.GetD3ColdCapability(Pdo->m_AcpiD3Cold.Context, D3ColdSupported);
608 Pdo->m_Child->m_Port->HasProperty(PortProperty::Removable))
609 {
610 DPRINT1("Platform claims D3cold for a removable port %u\n", Pdo->m_PortNumber);
611 }
612
613 return Status;
614}
615
617static
619NTAPI
620HubD3ColdGetBusDriverSupport(
621 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context,
623{
625
626 PAGED_CODE();
627
628 *D3ColdSupported = !Pdo->m_Child->m_Port->HasProperty(PortProperty::Removable);
629 return STATUS_SUCCESS;
630}
631
632/* A device that was reset on resume lost its state, which is what the client asks */
634static
635VOID
636NTAPI
637HubD3ColdGetLastTransition(
638 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context,
640{
642
644
645 if (Pdo->m_AcpiD3Cold.GetLastTransitionStatus != NULL)
646 {
647 Pdo->m_AcpiD3Cold.GetLastTransitionStatus(Pdo->m_AcpiD3Cold.Context, LastTransitionStatus);
649 return;
650 }
651
654}
655
656/* Asks the PDO's own stack, so only an ACPI filter above it can answer */
658static
659VOID
660NTAPI
661HubPdoQueryAcpiD3Cold(
662 _In_ HubPdo* Pdo)
663{
666 WDFIOTARGET Target;
669
670 PAGED_CODE();
671
672 Status = WdfIoTargetCreate(Pdo->m_Device, WDF_NO_OBJECT_ATTRIBUTES, &Target);
673 if (!NT_SUCCESS(Status))
674 {
675 DPRINT1("D3cold query target on port %u not created 0x%lx\n", Pdo->m_PortNumber, Status);
676 return;
677 }
678
679 WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&Open, WdfDeviceWdmGetDeviceObject(Pdo->m_Device));
680
681 Status = WdfIoTargetOpen(Target, &Open);
682 if (!NT_SUCCESS(Status))
683 DPRINT1("D3cold query target on port %u not opened 0x%lx\n", Pdo->m_PortNumber, Status);
684
685 if (NT_SUCCESS(Status))
686 {
688 Status = WdfIoTargetQueryForInterface(Target,
689 &GUID_D3COLD_SUPPORT_INTERFACE,
691 sizeof(Interface),
692 1,
693 Pdo);
694
695 /* Expected without an ACPI filter */
696 if (!NT_SUCCESS(Status))
697 DPRINT("No ACPI D3cold interface on port %u, 0x%lx\n", Pdo->m_PortNumber, Status);
698
699 if (NT_SUCCESS(Status))
700 {
701 if (Interface.GetD3ColdCapability != NULL &&
702 NT_SUCCESS(Interface.GetD3ColdCapability(Interface.Context, &Supported)) &&
703 Supported)
704 {
705 Pdo->m_Child->SetProperty(ChildProperty::AcpiAllowsD3Cold);
706 }
707
708 if (Interface.InterfaceDereference != NULL)
709 Interface.InterfaceDereference(Interface.Context);
710 }
711 }
712
714}
715
716/* Query interface */
717
718static
720NTAPI
722 _In_ HubPdo* Pdo,
724{
726 PD3COLD_SUPPORT_INTERFACE Interface = (PD3COLD_SUPPORT_INTERFACE)Stack->Parameters.QueryInterface.Interface;
727
728 if (Stack->Parameters.QueryInterface.Size != sizeof(*Interface) ||
729 Stack->Parameters.QueryInterface.Version != 1)
730 {
731 DPRINT("D3cold query on port %u with size %u version %u left alone\n",
732 Pdo->m_PortNumber, Stack->Parameters.QueryInterface.Size, Stack->Parameters.QueryInterface.Version);
733 return HubPdoCompleteAsIs(Irp);
734 }
735
736 /* An ACPI filter above already filled it on the way down; keep its copy */
737 if (Irp->IoStatus.Status == STATUS_SUCCESS)
738 {
739 if (Interface->Size != sizeof(*Interface) || Interface->Version != 1)
740 {
741 DPRINT1("ACPI D3cold interface on port %u has size %u version %u\n",
742 Pdo->m_PortNumber, Interface->Size, Interface->Version);
744 }
745
746 Pdo->m_AcpiD3Cold = *Interface;
747 }
748 else
749 {
750 Interface->Size = sizeof(*Interface);
751 Interface->Version = 1;
752 }
753
754 Interface->Context = Pdo;
755 Interface->InterfaceReference = HubD3ColdReference;
756 Interface->InterfaceDereference = HubD3ColdDereference;
757 Interface->SetD3ColdSupport = HubD3ColdSetSupport;
758 Interface->GetIdleWakeInfo = HubD3ColdGetIdleWakeInfo;
759 Interface->GetD3ColdCapability = HubD3ColdGetCapability;
760 Interface->GetBusDriverD3ColdSupport = HubD3ColdGetBusDriverSupport;
761 Interface->GetLastTransitionStatus = HubD3ColdGetLastTransition;
762
764}
765
766static
768NTAPI
770 _In_ HubPdo* Pdo,
772{
774 const GUID* Type = Stack->Parameters.QueryInterface.InterfaceType;
776 HubChild* Child = Pdo->m_Child;
777
778 /* Placeholders answer nothing; the PDO's own D3cold probe is left to ACPI */
779 if (!Child->HasState(ChildState::WorkingDevice) ||
780 Stack->Parameters.QueryInterface.InterfaceSpecificData == Pdo)
781 {
782 DPRINT("Interface query on port %u left alone\n", Pdo->m_PortNumber);
783 return HubPdoCompleteAsIs(Irp);
784 }
785
786 if (IsEqualGUID(*Type, USB_BUS_INTERFACE_USBDI_GUID))
787 {
788 Stack->Parameters.QueryInterface.InterfaceSpecificData = Child->m_UsbDevice;
789 return HubPdoToController(Pdo, Irp);
790 }
791
792 /* The contract is recorded for every 602 or later client, not only exact matches */
793 if (IsEqualGUID(*Type, GUID_USBD_CLIENT_INTERFACE))
794 {
795 Stack->Parameters.QueryInterface.InterfaceSpecificData = Child->m_UsbDevice;
796 Client = (PUSBD_CLIENT_INTERFACE)Stack->Parameters.QueryInterface.Interface;
797
798 if (Stack->Parameters.QueryInterface.Size >= sizeof(*Client) ||
799 Stack->Parameters.QueryInterface.Version >= USBD_CLIENT_INTERFACE_VERSION)
800 {
801 Pdo->m_ClientContractVersion = Client->ClientContractVersion;
802 }
803
804 return HubPdoToController(Pdo, Irp);
805 }
806
807 if (IsEqualGUID(*Type, GUID_UCXHUB_STACK_INTERFACE))
808 return HubPdoToController(Pdo, Irp);
809
810 if (IsEqualGUID(*Type, GUID_D3COLD_SUPPORT_INTERFACE))
811 return HubPdoAnswerD3Cold(Pdo, Irp);
812
813 return HubPdoPassDown(Pdo->m_Device, Irp);
814}
815
816/* Parent interface of a child hub */
817
819static
821NTAPI
822HubPdoWasProgrammingLost(
824{
825 return ((HubPdo*)Context)->TestAndClearFlag(PdoFlag::ProgrammingLostOnReset);
826}
827
829static
831NTAPI
832HubPdoWasHubReset(
834{
836
837 if (!Pdo->HasFlag(PdoFlag::WasResetAtResume))
838 return FALSE;
839
840 Pdo->ClearFlag(PdoFlag::WasResetAtResume);
842 return TRUE;
843}
844
845/* A view of the PDO's string, not a copy */
847static
848VOID
849NTAPI
850HubPdoGetSymbolicLink(
853{
855
857
858 if (Pdo->m_SymbolicLink != NULL)
860}
861
862/* SuperSpeedPlus is the only enhanced SuperSpeed mode the hub tells apart */
863static
865NTAPI
868{
869 return (Child->m_Kind & DSM_KIND_SUPER_SPEED) && Child->m_SublinkSpeedAttrCount != 0;
870}
871
872/* The requester's Size is only checked by KMDF's template test */
873static
875NTAPI
877 _In_ WDFDEVICE Device,
881{
882 HubPdo* Pdo = HubGetPdoContext(Device);
883 HubChild* Child = Pdo->m_Child;
884 HubFdo* Hub = Pdo->m_Hub;
885 HubPort* Port = Child->m_Port;
887 UCHAR Depth;
888
891
892 if (!Child->HasProperty(ChildProperty::IsHub))
893 {
894 DPRINT1("Parent interface query on port %u, which is not a hub\n", Pdo->m_PortNumber);
895 return STATUS_UNSUCCESSFUL;
896 }
897
898 Depth = Hub->m_Parent.HubDepth + 1;
899
900 Parent->Header.Size = sizeof(*Parent);
901 Parent->Header.Version = UCXHUB_PARENT_INTERFACE_VERSION;
902 Parent->Header.Context = Pdo;
903 Parent->Header.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
904 Parent->Header.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
905
906 Parent->HubDepth = Depth;
907 Parent->ParentCanWake = Child->HasProperty(ChildProperty::RemoteWakeCapable);
908
909 Parent->HubTopologyAddress = Hub->m_Parent.HubTopologyAddress;
910 if (Depth == 1)
911 Parent->HubTopologyAddress.RootHubPortNumber = Pdo->m_PortNumber;
912 else if (Depth - 2 < (UCHAR)RTL_NUMBER_OF(Parent->HubTopologyAddress.HubPortNumber))
913 Parent->HubTopologyAddress.HubPortNumber[Depth - 2] = Pdo->m_PortNumber;
914
915 Parent->HubSpeed = Child->Speed();
916 Parent->IsEnhancedSuperSpeed = HubPdoIsEnhancedSuperSpeed(Child);
917 Parent->Hub = Child->m_UsbDevice;
918
919 /* A hub on a root port hands down its own tunnel state; deeper hubs inherit it */
920 Parent->TunnelState = (Depth == 1) ? Child->m_TunnelState : Hub->m_Parent.TunnelState;
921
922 Parent->ParentLostStateDuringResume = HubPdoWasProgrammingLost;
923 Parent->ParentResetDuringResume = HubPdoWasHubReset;
924 Parent->ConnectorId = &Port->m_ConnectorId;
925 Parent->QueryHubLinkName = HubPdoGetSymbolicLink;
926
928 {
929 Parent->FirstCompanionPort = Port->m_FirstCompanionPort;
930 Parent->LastCompanionPort = Port->m_LastCompanionPort;
931
933 Parent->ParentCanWake = FALSE;
934 }
935
936 Pdo->m_ChildHubFdo = Parent->ChildHubObject;
937 DPRINT("Child hub %p on port %u at depth %u\n", Pdo->m_ChildHubFdo, Pdo->m_PortNumber, Depth);
938 return STATUS_SUCCESS;
939}
940
941/* Location interface */
942
944static
946NTAPI
947HubPdoGetLocationString(
950{
952 const SIZE_T Count = 10;
955
956 PAGED_CODE();
957
959
961 if (Buffer == NULL)
962 {
963 DPRINT1("No memory for the location string of port %u\n", Child->m_Port->Number());
965 }
966
967 /* Filling behind the NUL leaves the second NUL of the multi string */
969 L"USB(%d)", Child->m_Port->Number());
970 if (!NT_SUCCESS(Status))
971 DPRINT1("Location string failed 0x%lx\n", Status);
972
974 return STATUS_SUCCESS;
975}
976
977/* PnP IRP preprocessing */
978
979/* A device id query before start brings the device back for an AddDevice that sends I/O */
981static
982VOID
983NTAPI
984HubPdoPreStartOnQueryId(
985 _In_ HubPdo* Pdo,
986 _In_ PIRP Irp)
987{
989 WDFDEVICE HubDevice = Pdo->m_Hub->m_Device;
991
992 if (Pdo->HasFlag(PdoFlag::Started) ||
993 Stack->Parameters.QueryId.IdType != BusQueryDeviceID ||
995 {
996 return;
997 }
998
1001 {
1002 DPRINT1("Hub did not power up for pre start 0x%lx\n", Status);
1003 return;
1004 }
1005
1008}
1009
1010static
1012NTAPI
1014 _In_ WDFDEVICE Device,
1016{
1017 HubPdo* Pdo = HubGetPdoContext(Device);
1018 HubChild* Child = Pdo->m_Child;
1020 NTSTATUS EntryStatus = Irp->IoStatus.Status;
1021
1022 switch (Stack->MinorFunction)
1023 {
1025 return HubPdoQueryInterface(Pdo, Irp);
1026
1028 return HubIdQueryDeviceText(Child, Irp);
1029
1030 case IRP_MN_QUERY_ID:
1031 HubPdoPreStartOnQueryId(Pdo, Irp);
1032 return HubPdoPassDown(Device, Irp);
1033
1035 Pdo->m_ChildHubFdo = NULL;
1036 return HubPdoPassDown(Device, Irp);
1037
1038 /* KMDF leaves STATUS_NOT_SUPPORTED here; the EHCI stack answered success */
1040 HubPdoDispatchAndWait(Device, Irp);
1041
1042 HubPdoQueryAcpiD3Cold(Pdo);
1043 if (Child->m_Billboard != NULL)
1044 HubPdoPublishBillboard(Pdo);
1045 if (Child->HasProperty(ChildProperty::DualRole))
1046 HubPdoPublishDualRole(Pdo);
1047 HubPdoPublishTunnelState(Pdo);
1048
1050
1051 /* Kept synchronous; the EHCI stack never pended these */
1054 HubPdoDispatchAndWait(Device, Irp);
1055 return HubPdoCompleteAsIs(Irp);
1056
1057 /* KMDF writes success; the status from above is returned instead */
1059 HubPdoDispatchAndWait(Device, Irp);
1060 return HubPdoCompleteIrp(Irp, EntryStatus);
1061
1063 HubPdoDispatchAndWait(Device, Irp);
1064
1065 if (Irp->IoStatus.Information == 0)
1066 return HubPdoCompleteIrp(Irp, EntryStatus);
1067
1068 if (Child->m_EnumMessageId != 0)
1069 {
1070 DPRINT1("Port %u reports enumeration problem %lu\n", Pdo->m_PortNumber, Child->m_EnumMessageId);
1071 HubWriteEnumerationFailureCode(Child);
1072 HubReportPnpProblem(Device, Child->m_EnumMessageId);
1073 }
1074
1075 return HubPdoCompleteAsIs(Irp);
1076
1077 default:
1078 return HubPdoPassDown(Device, Irp);
1079 }
1080}
1081
1082/* Power IRP preprocessing */
1083
1084static
1085VOID
1086NTAPI
1088 _In_ WDFWORKITEM WorkItem)
1089{
1090 IoCompleteRequest(HubGetPdoIrpWork(WorkItem)->Irp, IO_NO_INCREMENT);
1092}
1093
1094/*
1095 * KMDF may complete a D IRP inside its power machine; finishing it on a work
1096 * item keeps a driver above from sending the next IRP on this same thread.
1097 */
1098static
1100NTAPI
1103 _In_ PIRP Irp,
1104 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
1105{
1106 HubPdo* Pdo = (HubPdo*)Context;
1109 WDFWORKITEM WorkItem;
1111
1113
1114 if (Irp->PendingReturned)
1116
1118 Config.AutomaticSerialization = FALSE;
1120 Attributes.ParentObject = Pdo->m_Device;
1121
1122 Status = WdfWorkItemCreate(&Config, &Attributes, &WorkItem);
1123 if (!NT_SUCCESS(Status))
1124 {
1125 DPRINT1("Port %u power IRP %p completes inline, work item failed 0x%lx\n",
1126 Pdo->m_PortNumber, Irp, Status);
1128 }
1129
1130 HubGetPdoIrpWork(WorkItem)->Irp = Irp;
1133}
1134
1135/* A client that went D2 then D3 on a system sleep gets its wait wake and idle IRPs back */
1136static
1138NTAPI
1140 _In_ WDFDEVICE Device,
1142{
1143 HubPdo* Pdo = HubGetPdoContext(Device);
1144 HubChild* Child = Pdo->m_Child;
1148
1149 if (Stack->Parameters.Power.Type != DevicePowerState)
1150 return HubPdoPassDown(Device, Irp);
1151
1152 Target = Stack->Parameters.Power.State.DeviceState;
1153 DPRINT("Port %u device power IRP to D%d\n", Pdo->m_PortNumber, (int)Target - 1);
1154
1155 if (Target == PowerDeviceD3 && Child->m_PowerState == PowerDeviceD2)
1156 {
1157 /* Fails when no wait wake IRP is pending, which is fine */
1158 Status = WdfDeviceIndicateWakeStatus(Device, STATUS_POWER_STATE_INVALID);
1159 if (!NT_SUCCESS(Status))
1160 DPRINT1("Port %u D2 to D3 wake status not taken 0x%lx\n", Pdo->m_PortNumber, Status);
1161
1162 Pdo->m_Idle.Post(IdleEvent::PoweringDown, NULL);
1163 }
1164
1165 Child->m_PowerState = Target;
1166
1167 /* The completion may finish the IRP later on a work item, so it is always pending */
1172 return STATUS_PENDING;
1173}
1174
1175/* PnP and power callbacks */
1176
1178static
1180NTAPI
1182 _In_ WDFDEVICE Device,
1183 _In_ WDFCMRESLIST ResourcesRaw,
1185{
1187 HubPdo* Pdo = HubGetPdoContext(Device);
1188 HubChild* Child = Pdo->m_Child;
1189 HubFdo* Hub = Pdo->m_Hub;
1193
1196
1197 PAGED_CODE();
1198
1199 DPRINT("Child PDO %p on port %u prepare hardware\n", Device, Pdo->m_PortNumber);
1200
1201 /* From here on a device id query no longer pre starts the device */
1203
1205
1206 /* The state is the controller's answer from the device update, which ran before */
1208 {
1210 {
1211 DPRINT("Port %u keeps U2 off for its tunneled device\n", Pdo->m_PortNumber);
1213 }
1214
1215 HubUsb4AcquireHostPower(Child->m_Port);
1216 }
1217
1221
1222 if (Child->HasProperty(ChildProperty::IsHub))
1223 {
1224 if (Hub->m_Parent.HubDepth >= Child->m_Port->m_Info.TotalHubDepth)
1225 {
1226 DPRINT1("Hub on port %u nested too deeply, depth %u\n", Pdo->m_PortNumber, Hub->m_Parent.HubDepth);
1227 Child->m_Port->m_ConnectionStatus = DeviceHubNestedTooDeeply;
1228 HubWmiNotifyHubNestedTooDeeply(Hub, Pdo->m_PortNumber);
1229 return STATUS_UNSUCCESSFUL;
1230 }
1231
1232 InterfaceGuid = &GUID_DEVINTERFACE_USB_HUB;
1233 }
1234 else
1235 {
1236 InterfaceGuid = &GUID_DEVINTERFACE_USB_DEVICE;
1237 }
1238
1239 Status = WdfDeviceCreateDeviceInterface(Device, InterfaceGuid, NULL);
1240 if (!NT_SUCCESS(Status))
1241 {
1242 DPRINT1("Port %u device interface not created 0x%lx\n", Pdo->m_PortNumber, Status);
1243 return Status;
1244 }
1245
1246 if (Pdo->m_SymbolicLink == NULL)
1247 {
1249 Attributes.ParentObject = Device;
1250
1251 Status = WdfStringCreate(NULL, &Attributes, &Pdo->m_SymbolicLink);
1252 if (!NT_SUCCESS(Status))
1253 {
1254 DPRINT1("Port %u symbolic link string not created 0x%lx\n", Pdo->m_PortNumber, Status);
1255 return Status;
1256 }
1257 }
1258
1259 Status = WdfDeviceRetrieveDeviceInterfaceString(Device, InterfaceGuid, NULL, Pdo->m_SymbolicLink);
1260 if (!NT_SUCCESS(Status))
1261 {
1262 DPRINT1("Port %u symbolic link not retrieved 0x%lx\n", Pdo->m_PortNumber, Status);
1263 return Status;
1264 }
1265
1266 Status = HubWriteDeviceString(Child, &SymbolicName, Pdo->m_SymbolicLink);
1267 if (!NT_SUCCESS(Status))
1268 {
1269 DPRINT1("Port %u symbolic link not written to the registry 0x%lx\n", Pdo->m_PortNumber, Status);
1270 return Status;
1271 }
1272
1274 Pdo->m_FailRequests = FALSE;
1275
1276 if (!Child->HasProperty(ChildProperty::IsHub) && !Child->HasProperty(ChildProperty::IsComposite))
1277 HubWmiRegisterDevice(Device);
1278
1279 return STATUS_SUCCESS;
1280}
1281
1283static
1285NTAPI
1287 _In_ WDFDEVICE Device,
1288 _In_ WDFCMRESLIST ResourcesTranslated)
1289{
1290 HubPdo* Pdo = HubGetPdoContext(Device);
1291 HubChild* Child = Pdo->m_Child;
1292
1294
1295 PAGED_CODE();
1296
1297 DPRINT("Child PDO %p on port %u release hardware\n", Device, Pdo->m_PortNumber);
1298
1299 Pdo->m_FailRequests = TRUE;
1301
1302 /* A rebalance keeps the UXD and dual role state */
1303 if (Pdo->TestAndClearFlag(PdoFlag::QueryStopped))
1304 return STATUS_SUCCESS;
1305
1306 if (Pdo->TestAndClearFlag(PdoFlag::QueryRemoved))
1307 HubPurgeUxdState(Child, HubUxdEvent::Disable);
1308
1310 Child->ClearProperty(ChildProperty::DualRole);
1311
1312 /* A rebalance stop returns early above and skips this release, so the restart takes another reference */
1314 HubUsb4ReleaseHostPower(Child->m_Port);
1315
1316 return STATUS_SUCCESS;
1317}
1318
1319static
1321NTAPI
1323 _In_ WDFDEVICE Device)
1324{
1325 HubGetPdoContext(Device)->SetFlag(PdoFlag::QueryStopped);
1326 return STATUS_SUCCESS;
1327}
1328
1329static
1331NTAPI
1333 _In_ WDFDEVICE Device)
1334{
1335 HubGetPdoContext(Device)->SetFlag(PdoFlag::QueryRemoved);
1336 return STATUS_SUCCESS;
1337}
1338
1339/* KMDF may skip ReportedMissing when the whole hub is gone, so the child list is cleaned here */
1341static
1342VOID
1343NTAPI
1345 _In_ WDFDEVICE Device)
1346{
1347 HubPdo* Pdo = HubGetPdoContext(Device);
1348 HubChild* Child = Pdo->m_Child;
1349 HubFdo* Hub = Pdo->m_Hub;
1350
1351 PAGED_CODE();
1352
1353 DPRINT("Child PDO %p on port %u surprise removed\n", Device, Pdo->m_PortNumber);
1354
1357 Child->m_SerialNumber != NULL)
1358 {
1360 }
1361
1362 Pdo->m_FailRequests = TRUE;
1363 HubPdoReleaseBillboard(Pdo);
1364}
1365
1366static
1367VOID
1368NTAPI
1370 _In_ WDFDEVICE Device)
1371{
1372 HubPdo* Pdo = HubGetPdoContext(Device);
1373
1374 DPRINT("Child PDO %p on port %u reported missing\n", Device, Pdo->m_PortNumber);
1375 Pdo->m_Child->Post(DsmEvent::PdoReportedMissing);
1376}
1377
1378/* MS OS extended properties go in here, before the function driver's AddDevice */
1380static
1382NTAPI
1384 _In_ WDFDEVICE Device,
1386{
1387 HubPdo* Pdo = HubGetPdoContext(Device);
1388 WDFDEVICE HubDevice = Pdo->m_Hub->m_Device;
1390
1392
1393 PAGED_CODE();
1394
1396 if (!NT_SUCCESS(Status))
1397 {
1398 DPRINT1("Hub did not power up for the resource query 0x%lx\n", Status);
1399 return STATUS_SUCCESS;
1400 }
1401
1402 /* The driver wait timer may have disabled the device meanwhile */
1403 if (!Pdo->HasFlag(PdoFlag::Started))
1404 HubPdoPreStart(Pdo->m_Child);
1405
1406 HubPdoPostAndWait(Pdo->m_Child, DsmEvent::PdoInstallMsOsExt, "PdoInstallMsOsExt");
1407
1409 return STATUS_SUCCESS;
1410}
1411
1412/* An unreported PDO skips the device machine */
1414static
1415VOID
1416NTAPI
1419{
1420 HubPdo* Pdo = HubGetPdoContext(Object);
1421 HubChild* Child = Pdo->m_Child;
1422 HubFdo* Hub = Pdo->m_Hub;
1423 UCXHUB_STOP_IDLE_CONTEXT StopIdle;
1425 ULONG Index;
1426
1427 PAGED_CODE();
1428
1429 DPRINT("Child PDO %p on port %u cleanup, reported %u\n", Object, Pdo->m_PortNumber, Pdo->m_Reported);
1430
1431 for (Index = 0; Index < HUB_PDO_LPM_SETTINGS; Index++)
1432 {
1433 if (Pdo->m_LpmSettings[Index] == NULL)
1434 continue;
1435
1436 Status = HubDriver.UnregisterPowerSetting(Pdo->m_LpmSettings[Index]);
1437 if (!NT_SUCCESS(Status))
1438 DPRINT1("LPM setting %lu unregister failed 0x%lx\n", Index, Status);
1439 Pdo->m_LpmSettings[Index] = NULL;
1440 }
1441
1442 if (Pdo->HasFlag(PdoFlag::IdleMachineStarted))
1443 Pdo->m_Idle.Post(IdleEvent::Cleanup, NULL);
1444
1445 if (Pdo->m_Reported)
1446 {
1447 /* The device machine deletes the device from a controller that may be idle */
1448 RtlZeroMemory(&StopIdle, sizeof(StopIdle));
1450
1452 HubPdoReleaseBillboard(Pdo);
1453
1455 }
1456
1458
1459 if (Pdo->m_StartFailData != NULL)
1460 {
1461 ExFreePoolWithTag(Pdo->m_StartFailData, HUB_TAG_DEVICE);
1462 Pdo->m_StartFailData = NULL;
1463 }
1464}
1465
1466static
1468NTAPI
1470 _In_ WDFDEVICE Device)
1471{
1472 HubGetPdoContext(Device)->SetFlag(PdoFlag::InD0);
1473 return STATUS_SUCCESS;
1474}
1475
1476static
1478NTAPI
1480 _In_ WDFDEVICE Device)
1481{
1482 HubPdo* Pdo = HubGetPdoContext(Device);
1483
1484 Pdo->ClearFlag(PdoFlag::InD0);
1485 return STATUS_SUCCESS;
1486}
1487
1489static
1491NTAPI
1493 _In_ WDFDEVICE Device,
1495{
1496 HubPdo* Pdo = HubGetPdoContext(Device);
1498
1500
1501 PAGED_CODE();
1502
1503 DPRINT("Child PDO %p on port %u D0 entry from %d\n", Device, Pdo->m_PortNumber, (int)PreviousState);
1504
1505 Pdo->m_WdfPowerState = WdfPowerDeviceD0;
1507
1508 /* Activating the hub's PoFx component for the host router is not supported */
1510 DPRINT("Port %u USB4 power component activation is not available\n", Pdo->m_PortNumber);
1511
1512 Status = HubPdoPostAndWait(Pdo->m_Child, DsmEvent::PdoPowerUp, "PdoPowerUp");
1513 if (!NT_SUCCESS(Status))
1514 DPRINT1("Port %u D0 entry failed 0x%lx\n", Pdo->m_PortNumber, Status);
1515
1516 return Status;
1517}
1518
1519/* A D3Final with a system power action posts PdoPowerDown */
1521static
1523NTAPI
1525 _In_ WDFDEVICE Device,
1527{
1528 HubPdo* Pdo = HubGetPdoContext(Device);
1529 HubChild* Child = Pdo->m_Child;
1533
1534 PAGED_CODE();
1535
1536 Pdo->m_WdfPowerState = TargetState;
1537 KeClearEvent(&Child->m_PnpEvent);
1538 Action = WdfDeviceGetSystemPowerAction(Device);
1539
1540 DPRINT("Child PDO %p on port %u D0 exit to %d, action %d\n",
1541 Device, Pdo->m_PortNumber, (int)TargetState, (int)Action);
1542
1544 HubRecordSelectiveSuspend(Child);
1545
1547 {
1549 }
1551 {
1553 }
1554 else
1555 {
1556 /* Wait wake and idle IRPs complete when the device goes to D3 */
1558 {
1559 if (Pdo->HasFlag(PdoFlag::WakeArmRequested))
1560 {
1561 Status = WdfDeviceIndicateWakeStatus(Device, STATUS_POWER_STATE_INVALID);
1562 if (!NT_SUCCESS(Status))
1563 DPRINT1("Wake status not taken 0x%lx\n", Status);
1564 Pdo->ClearFlag(PdoFlag::WakeArmRequested);
1565 }
1566
1567 if (!Child->HasProperty(ChildProperty::AllowIdleIrpInD3))
1568 Pdo->m_Idle.Post(IdleEvent::PoweringDown, NULL);
1569 }
1570
1572 }
1573
1574 Child->Post(Event);
1575 HubWaitForPnpEvent(&Child->m_PnpEvent, "PdoPowerDown", Child->m_Object);
1576 Status = Child->m_PnpStatus;
1577 if (!NT_SUCCESS(Status))
1578 DPRINT1("Port %u D0 exit failed 0x%lx\n", Pdo->m_PortNumber, Status);
1579
1580 if (WdfTimerStop(Child->m_BandwidthRetryTimer, TRUE))
1581 {
1582 DPRINT1("Port %u ran out of bandwidth\n", Pdo->m_PortNumber);
1583 HubWmiNotifyInsufficientBandwidth(Pdo->m_Hub, Pdo->m_PortNumber);
1584 }
1585
1586 /* Idling the hub's PoFx component for the host router is not supported */
1588 DPRINT("Port %u USB4 power component idling is not available\n", Pdo->m_PortNumber);
1589
1590 return Status;
1591}
1592
1593/* Wake */
1594
1595static
1596VOID
1597NTAPI
1599 _In_ HubPdo* Pdo)
1600{
1602 KIRQL OldIrql;
1603
1605 Status = WdfDeviceIndicateWakeStatus(Pdo->m_Device, STATUS_SUCCESS);
1607
1608 if (!NT_SUCCESS(Status))
1609 DPRINT1("Wake status not taken 0x%lx\n", Status);
1610}
1611
1612/* A notification canceled by DisableWakeAtBus still reports success; KMDF ignores it then */
1613static
1614VOID
1615NTAPI
1617 _In_ WDFREQUEST Request,
1618 _In_ WDFIOTARGET Target,
1621{
1622 HubPdo* Pdo = (HubPdo*)Context;
1623
1627
1628 DPRINT("Port %u wake notification done 0x%lx\n", Pdo->m_PortNumber, Params->IoStatus.Status);
1630 KeSetEvent(&Pdo->m_WakeDone, IO_NO_INCREMENT, FALSE);
1631}
1632
1633static
1635NTAPI
1637 _In_ HubPdo* Pdo)
1638{
1641 WDFREQUEST Request = Pdo->m_WakeRequest;
1643
1645 Status = WdfRequestReuse(Request, &Reuse);
1646 if (!NT_SUCCESS(Status))
1647 DPRINT1("Wake request reuse failed 0x%lx\n", Status);
1648
1649 RtlZeroMemory(&Pdo->m_WakeBlock, sizeof(Pdo->m_WakeBlock));
1650 Pdo->m_WakeBlock.Size = sizeof(Pdo->m_WakeBlock);
1651 KeClearEvent(&Pdo->m_WakeDone);
1652
1653 RtlZeroMemory(&Stack, sizeof(Stack));
1654 Stack.MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1655 Stack.Parameters.Others.Argument1 = &Pdo->m_WakeBlock;
1656 Stack.Parameters.Others.Argument2 = Pdo->m_Child->m_UsbDevice;
1657 Stack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION;
1658
1659 WdfRequestWdmFormatUsingStackLocation(Request, &Stack);
1660 WdfRequestSetCompletionRoutine(Request, HubPdoWakeNotificationComplete, Pdo);
1661
1662 if (!WdfRequestSend(Request, Pdo->m_Hub->m_RootHubTarget, WDF_NO_SEND_OPTIONS))
1663 {
1664 Status = WdfRequestGetStatus(Request);
1665 DPRINT1("Port %u wake notification not sent 0x%lx\n", Pdo->m_PortNumber, Status);
1666 return Status;
1667 }
1668
1669 return STATUS_SUCCESS;
1670}
1671
1672/* WaitWakePending stays set on failure */
1673static
1675NTAPI
1677 _In_ WDFDEVICE Device,
1679{
1680 HubPdo* Pdo = HubGetPdoContext(Device);
1681 HubChild* Child = Pdo->m_Child;
1683
1684 DPRINT("Port %u enable wake for S%d\n", Pdo->m_PortNumber, (int)PowerState - 1);
1685
1686 Pdo->SetFlag(PdoFlag::WaitWakePending);
1687
1688 /* Hubs pass their children's wake on but are not armed for Sx here */
1690 return STATUS_SUCCESS;
1691
1692 if (!Child->HasProperty(ChildProperty::RemoteWakeCapable))
1693 {
1694 DPRINT1("Port %u device cannot wake\n", Pdo->m_PortNumber);
1695 return STATUS_NOT_SUPPORTED;
1696 }
1697
1699 return STATUS_SUCCESS;
1700
1701 if (Child->m_Kind & DSM_KIND_SUPER_SPEED)
1702 {
1704 if (NT_SUCCESS(Status))
1706 }
1707
1709 return Status;
1710}
1711
1713static
1714VOID
1715NTAPI
1717 _In_ WDFDEVICE Device)
1718{
1719 HubPdo* Pdo = HubGetPdoContext(Device);
1720
1721 PAGED_CODE();
1722
1723 DPRINT("Port %u disable wake\n", Pdo->m_PortNumber);
1724
1725 Pdo->ClearFlag(PdoFlag::WakeArmRequested);
1726 Pdo->ClearFlag(PdoFlag::WaitWakePending);
1727
1729 return;
1730
1731 if (Pdo->TestAndClearFlag(PdoFlag::WakeNotificationSent))
1732 {
1733 WdfRequestCancelSentRequest(Pdo->m_WakeRequest);
1735 }
1736}
1737
1738/* LPM power settings; the link power management policy value length is not checked */
1739static
1741NTAPI
1747{
1750 ULONG Slot;
1751 ULONG Setting;
1752 ULONG Accept;
1753 ULONG Initiate;
1754
1755 for (Slot = 0; Slot < HUB_PDO_LPM_SETTINGS; Slot++)
1756 {
1759 {
1760 break;
1761 }
1762 }
1763
1765 return STATUS_SUCCESS;
1766
1767 if (Slot != HubLpmPolicy && ValueLength < sizeof(ULONG))
1768 {
1769 DPRINT1("LPM setting %lu of %p has only %lu bytes\n", Slot, Child, ValueLength);
1771 }
1772
1773 Setting = *(PULONG)Value;
1774
1775 switch (Slot)
1776 {
1777 case HubLpmPolicy:
1778 if (Setting > 3)
1779 {
1780 DPRINT1("LPM policy %lu of %p is out of range\n", Setting, Child);
1782 }
1783
1784 if (Setting == 0)
1785 {
1786 Policy = 0;
1787 break;
1788 }
1789
1792 if (Setting == 1)
1794 else if (Setting == 3)
1796 break;
1797
1798 case HubLpmU1Enable:
1799 if (Setting != 0)
1801 else
1802 Policy &= ~HUB_LPM_POLICY_U1_ENABLED;
1803 break;
1804
1805 case HubLpmU2Enable:
1806 if (Setting != 0)
1808 else
1809 Policy &= ~HUB_LPM_POLICY_U2_ENABLED;
1810 break;
1811
1812 default:
1815
1816 if (Setting == 0)
1817 Policy |= Accept | Initiate;
1818 else if (Setting == 1)
1819 Policy = (Policy | Accept) & ~Initiate;
1820 else if (Setting == 2)
1821 Policy &= ~(Accept | Initiate);
1822 break;
1823 }
1824
1825 if (Policy != Child->m_LpmPolicy)
1826 {
1827 DPRINT("LPM policy of %p now 0x%lx\n", Child, Policy);
1828 Child->m_LpmPolicy = Policy;
1830 }
1831
1832 return STATUS_SUCCESS;
1833}
1834
1835/* The power manager calls back at once with the current values */
1837static
1838VOID
1839NTAPI
1841 _In_ HubPdo* Pdo)
1842{
1843 HubChild* Child = Pdo->m_Child;
1844 const GUID* Settings;
1846 ULONG Index;
1847
1848 PAGED_CODE();
1849
1851 return;
1852
1854
1855 for (Index = 0; Index < HUB_PDO_LPM_SETTINGS; Index++)
1856 {
1857 Status = HubDriver.RegisterPowerSetting(WdfDeviceWdmGetDeviceObject(Pdo->m_Device),
1858 &Settings[Index],
1860 Child,
1861 &Pdo->m_LpmSettings[Index]);
1862 if (!NT_SUCCESS(Status))
1863 {
1864 DPRINT1("LPM setting %lu register failed 0x%lx\n", Index, Status);
1865 Pdo->m_LpmSettings[Index] = NULL;
1866 }
1867 }
1868}
1869
1870/* Client internal IOCTLs */
1871
1872/* KMDF can fail a URB before the device machine sees it; give it a USBD status then */
1873static
1875NTAPI
1878 _In_ PIRP Irp,
1879 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
1880{
1882 NTSTATUS Status = Irp->IoStatus.Status;
1883
1885
1886 if (!NT_SUCCESS(Status) &&
1887 Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
1888 {
1889 PURB Urb = (PURB)Stack->Parameters.Others.Argument1;
1890 if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS)
1891 Urb->UrbHeader.Status = HubNtStatusToUsbd(Status);
1892 }
1893
1896}
1897
1898/* Callers must be at PASSIVE_LEVEL */
1899static
1901NTAPI
1903 _In_ HubPdo* Pdo,
1905 _In_ WDFQUEUE Queue)
1906{
1907 KEVENT Event;
1909
1913
1914 /* On failure KMDF completes the IRP, so the completion routine still runs */
1915 Status = WdfDeviceWdmDispatchIrpToIoQueue(Pdo->m_Device, Irp, Queue, WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP);
1916 if (!NT_SUCCESS(Status))
1917 DPRINT1("Dispatch to queue failed 0x%lx\n", Status);
1918
1920
1921 Status = Irp->IoStatus.Status;
1923 return Status;
1924}
1925
1926static
1928NTAPI
1930 _In_ HubPdo* Pdo,
1932{
1934 return WdfDeviceWdmDispatchIrpToIoQueue(Pdo->m_Device, Irp, Pdo->m_Queue, WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP);
1935}
1936
1937static
1938VOID
1939NTAPI
1941 _In_ HubPdo* Pdo,
1943{
1944 Urb->UrbHeader.UsbdDeviceHandle = Pdo->m_Child->m_UsbDevice;
1945}
1946
1947/* A pipe request length error is reported as an invalid function */
1948static
1950NTAPI
1953{
1954 USHORT Function = Urb->UrbHeader.Function;
1955
1956 if (Urb->UrbHeader.Length < sizeof(struct _URB_HEADER))
1957 DPRINT1("URB %p header length %u too small\n", Urb, Urb->UrbHeader.Length);
1958
1959 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
1960 Urb->UrbHeader.UsbdFlags = 0;
1961
1963 {
1964 DPRINT1("URB %p has invalid function 0x%x\n", Urb, Function);
1965 Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
1967 }
1968
1970 Function == URB_FUNCTION_SYNC_RESET_PIPE ||
1971 Function == URB_FUNCTION_SYNC_CLEAR_STALL) &&
1972 Urb->UrbHeader.Length != sizeof(struct _URB_PIPE_REQUEST))
1973 {
1974 DPRINT1("Pipe URB %p length %u, expected %lu\n",
1975 Urb, Urb->UrbHeader.Length, (ULONG)sizeof(struct _URB_PIPE_REQUEST));
1976 Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
1978 }
1979
1980 return STATUS_SUCCESS;
1981}
1982
1983static
1984PVOID
1985NTAPI
1987 _In_ PVOID Pointer,
1989{
1990 if (Mdl != NULL)
1992
1993 return Pointer;
1994}
1995
1996/* Language and the device descriptor index are ignored */
1997static
1999NTAPI
2001 _In_ HubPdo* Pdo,
2004{
2005 struct _URB_CONTROL_DESCRIPTOR_REQUEST* Request = &Urb->UrbControlDescriptorRequest;
2006 HubChild* Child = Pdo->m_Child;
2007 PVOID Source;
2008 PVOID Buffer;
2009 ULONG Size;
2011
2012 if (Child->m_DeviceDescriptor.bcdUSB <= 0x0200)
2013 {
2015 return HubPdoToController(Pdo, Irp);
2016 }
2017
2019 if (!NT_SUCCESS(Status))
2020 return HubPdoCompleteIrp(Irp, Status);
2021
2022 Buffer = HubPdoUrbBuffer(Request->TransferBuffer, Request->TransferBufferMDL);
2023 if (Buffer == NULL)
2024 {
2025 DPRINT1("Port %u descriptor URB %p has no buffer\n", Pdo->m_PortNumber, Urb);
2026 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
2028 }
2029
2030 if (Request->DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE)
2031 {
2032 Source = &Child->m_DeviceDescriptor;
2033 Size = min(sizeof(Child->m_DeviceDescriptor), Request->TransferBufferLength);
2034 }
2035 else if (Request->DescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE &&
2036 Request->Index == 0 &&
2037 Child->m_ConfigDescriptor != NULL)
2038 {
2039 Source = Child->m_ConfigDescriptor;
2040 Size = min((ULONG)Child->m_ConfigDescriptor->wTotalLength, Request->TransferBufferLength);
2041 }
2042 else
2043 {
2045 return HubPdoToController(Pdo, Irp);
2046 }
2047
2048 /* Compat: a default pipe request reads back as a control transfer */
2049 Urb->UrbControlTransfer.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
2050 if (Urb->UrbControlTransfer.TransferFlags & USBD_DEFAULT_PIPE_TRANSFER)
2051 Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
2052
2054 Request->TransferBufferLength = Size;
2056}
2057
2058/* NOT_SUPPORTED answers leave the URB status alone */
2059static
2061NTAPI
2063 _In_ HubPdo* Pdo,
2066{
2067 struct _URB_OS_FEATURE_DESCRIPTOR_REQUEST* Request = &Urb->UrbOSFeatureDescriptorRequest;
2068 HubChild* Child = Pdo->m_Child;
2070 const HubMsOs20SetHeader* Set;
2071 PVOID Buffer;
2072 ULONG Size;
2073
2074 if (Request->MS_FeatureDescriptorIndex == HUB_MSOS20_SET_INDEX)
2075 {
2076 Set = (const HubMsOs20SetHeader*)Child->m_MsOs20Set;
2077 if (Set == NULL)
2078 {
2079 DPRINT1("Port %u has no MS OS 2.0 descriptor set\n", Pdo->m_PortNumber);
2081 }
2082
2083 Buffer = HubPdoUrbBuffer(Request->TransferBuffer, Request->TransferBufferMDL);
2084 if (Buffer == NULL)
2085 {
2086 DPRINT1("Port %u MS OS 2.0 URB %p has no buffer\n", Pdo->m_PortNumber, Urb);
2088 }
2089
2090 Size = min((ULONG)Set->wTotalLength, Request->TransferBufferLength);
2092 Request->TransferBufferLength = Size;
2094 }
2095
2096 if (((BcdUsb >= 0x0200 || BcdUsb < 0x0100) && !Child->HasProperty(ChildProperty::MsOsNotSupported)) ||
2098 {
2099 /* The device's own vendor code goes into the request */
2100 Urb->UrbControlVendorClassRequest.Request = Child->m_MsOsVendorCode;
2102 return HubPdoToController(Pdo, Irp);
2103 }
2104
2105 DPRINT1("Port %u device does not support MS OS descriptors\n", Pdo->m_PortNumber);
2107}
2108
2109static
2111NTAPI
2114 _In_ PIRP Irp,
2115 _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
2116{
2118
2119 if (Irp->PendingReturned)
2121
2122 if (NT_SUCCESS(Irp->IoStatus.Status))
2124
2126}
2127
2128/* Function 0x3B: payload not decoded, so it is forwarded and only tracked like a select */
2129static
2131NTAPI
2133 _In_ HubPdo* Pdo,
2136{
2137 if (Pdo->m_ControllerTarget == NULL)
2138 {
2139 DPRINT1("Port %u has no controller target for URB %p\n", Pdo->m_PortNumber, Urb);
2141 }
2142
2146 return IoCallDriver(Pdo->m_ControllerTarget, Irp);
2147}
2148
2149/* Hubs select without waiting */
2150static
2152NTAPI
2154 _In_ HubPdo* Pdo,
2157{
2159
2160 switch (Urb->UrbHeader.Function)
2161 {
2167 return HubPdoToController(Pdo, Irp);
2168
2171
2175 case URB_FUNCTION_SYNC_RESET_PIPE:
2176 case URB_FUNCTION_SYNC_CLEAR_STALL:
2178 if (!NT_SUCCESS(Status))
2179 return HubPdoCompleteIrp(Irp, Status);
2180
2181 if (Pdo->m_Child->HasProperty(ChildProperty::IsHub))
2182 return HubPdoQueueAsync(Pdo, Irp);
2183
2184 return HubPdoQueueAndWait(Pdo, Irp, Pdo->m_Queue);
2185
2188
2189 case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR:
2191
2195 return HubPdoQueueAndWait(Pdo, Irp, Pdo->m_Queue);
2196
2198 if (Pdo->HasFlag(PdoFlag::FailGetStatus))
2199 {
2200 DPRINT1("Port %u GET_STATUS failed, the client said it is unsupported\n", Pdo->m_PortNumber);
2202 }
2203
2205 return HubPdoToController(Pdo, Irp);
2206
2207 /* UCX validates everything else */
2208 default:
2210 return HubPdoToController(Pdo, Irp);
2211 }
2212}
2213
2214/* Information may exceed the output buffer when the name does not fit */
2215static
2217NTAPI
2219 _In_ HubPdo* Pdo,
2221{
2223 PUSB_HUB_NAME HubName = (PUSB_HUB_NAME)Irp->AssociatedIrp.SystemBuffer;
2224 ULONG OutputLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
2226 PWCHAR Name;
2227 ULONG Chars;
2228 ULONG Index;
2229 ULONG NameBytes = 0;
2230
2231 if (HubName == NULL)
2232 {
2233 DPRINT1("Port %u hub name request has no buffer\n", Pdo->m_PortNumber);
2235 }
2236
2237 if (OutputLength < sizeof(*HubName))
2238 {
2239 DPRINT1("Port %u hub name buffer of %lu bytes too small\n", Pdo->m_PortNumber, OutputLength);
2241 }
2242
2243 if (!Pdo->m_Child->HasProperty(ChildProperty::IsHub))
2244 {
2245 HubName->ActualLength = sizeof(*HubName);
2246 HubName->HubName[0] = UNICODE_NULL;
2247 Irp->IoStatus.Information = sizeof(*HubName);
2249 }
2250
2251 RtlZeroMemory(HubName, OutputLength);
2252 HubPdoGetSymbolicLink(Pdo, &Link);
2253
2254 /* Drop the leading "\xxx\" of the symbolic link */
2255 Name = Link.Buffer;
2256 Chars = Link.Length / sizeof(WCHAR);
2257 if (Chars != 0 && Name[0] == L'\\')
2258 {
2259 for (Index = 1; Index < Chars && Name[Index] != L'\\'; Index++)
2260 ;
2261
2262 if (Index < Chars)
2263 {
2264 Name += Index + 1;
2265 NameBytes = (Chars - Index - 1) * sizeof(WCHAR);
2266 }
2267 }
2268
2269 if (NameBytes != 0 && OutputLength >= NameBytes + sizeof(*HubName))
2270 RtlCopyMemory(HubName->HubName, Name, NameBytes);
2271
2272 HubName->ActualLength = NameBytes + sizeof(*HubName);
2273 Irp->IoStatus.Information = HubName->ActualLength;
2275}
2276
2277/* The client's data is copied without probing */
2278static
2280NTAPI
2282 _In_ HubPdo* Pdo,
2284{
2286 ULONG Length;
2287
2288 if (Pdo->m_StartFailData != NULL || Data == NULL)
2289 {
2290 DPRINT1("Port %u start failure not recorded, data %p, already %p\n",
2291 Pdo->m_PortNumber, Data, Pdo->m_StartFailData);
2293 }
2294
2295 if (Data->LengthInBytes > HUB_START_FAIL_MAX)
2296 DPRINT1("Port %u start failure data of %lu bytes cut down\n", Pdo->m_PortNumber, Data->LengthInBytes);
2297
2298 Length = min(Data->LengthInBytes, (ULONG)HUB_START_FAIL_MAX);
2299 if (Length < sizeof(*Data))
2300 {
2301 DPRINT1("Port %u start failure data of %lu bytes too small\n", Pdo->m_PortNumber, Length);
2303 }
2304
2306 if (Copy == NULL)
2307 {
2308 DPRINT1("No memory for %lu bytes of port %u start failure data\n", Length, Pdo->m_PortNumber);
2310 }
2311
2313 Pdo->m_StartFailData = Copy;
2314 Pdo->m_Child->m_Port->m_ConnectionStatus = (USB_CONNECTION_STATUS)Copy->ConnectStatus;
2315 return STATUS_SUCCESS;
2316}
2317
2319static
2321NTAPI
2322HubPdoDeviceConfigInfo(
2323 _In_ HubPdo* Pdo,
2324 _Inout_opt_ PHUB_DEVICE_CONFIG_INFO Info)
2325{
2326 HubChild* Child = Pdo->m_Child;
2327 HubFdo* Hub = Pdo->m_Hub;
2328 USB_ID_STRING FriendlyName;
2330
2331 if (Info == NULL || Info->Version != 1)
2332 {
2333 DPRINT1("Port %u config info %p has a bad version\n", Pdo->m_PortNumber, Info);
2335 }
2336
2337 if (Info->Length != sizeof(*Info))
2338 {
2339 DPRINT1("Port %u config info length %lu, expected %lu\n",
2340 Pdo->m_PortNumber, Info->Length, (ULONG)sizeof(*Info));
2342 }
2343
2345 Info->Version = 1;
2346 Info->Length = sizeof(*Info);
2347
2350 {
2351 Info->HubFlags.HubIsHighSpeedCapable = 1;
2352 }
2353
2355 {
2356 Info->HubFlags.HubIsMultiTt = 1;
2357 Info->HubFlags.HubIsMultiTtCapable = 1;
2358 }
2359
2361 Info->HubFlags.HubIsHighSpeed = 1;
2363 Info->HubFlags.HubIsArmedWakeOnConnect = 1;
2365 Info->HubFlags.HubIsRoot = 1;
2366 if (Hub->m_MaxPortPower == 100)
2367 Info->HubFlags.HubIsBusPowered = 1;
2368
2369 /* Reserved[18] bit 0 says the UXD settings below are valid */
2371 {
2372 Info->Reserved[18] = 1;
2373 RtlCopyMemory(&Info->UxdSettings, &Child->m_Uxd, sizeof(Info->UxdSettings));
2374 }
2375
2376 Status = HubIdBuildCompatibleIds(Child, NULL, &Info->CompatibleIds);
2377 if (NT_SUCCESS(Status))
2378 Status = HubIdBuildHardwareIds(Child, NULL, &Info->HardwareIds);
2379
2381 {
2383 FriendlyName.LengthInBytes = Child->m_FriendlyNameLength;
2384 FriendlyName.Buffer = Child->m_FriendlyName;
2385 Status = HubIdListCopy(&Info->DeviceDescription, &FriendlyName);
2386 }
2387
2388 if (!NT_SUCCESS(Status))
2389 {
2390 HubIdListFree(&Info->CompatibleIds);
2391 HubIdListFree(&Info->HardwareIds);
2392 HubIdListFree(&Info->DeviceDescription);
2393 }
2394
2395 return Status;
2396}
2397
2398static
2400NTAPI
2402 _In_ HubPdo* Pdo,
2403 _Out_opt_ PUSB_TOPOLOGY_ADDRESS Address)
2404{
2405 HubFdo* Hub = Pdo->m_Hub;
2407
2408 if (Address == NULL)
2409 {
2410 DPRINT1("Port %u topology address request has no buffer\n", Pdo->m_PortNumber);
2412 }
2413
2415
2416 if (Depth == 0)
2417 Address->RootHubPortNumber = Pdo->m_PortNumber;
2418 else if (Depth - 1 < (UCHAR)RTL_NUMBER_OF(Address->HubPortNumber))
2419 Address->HubPortNumber[Depth - 1] = Pdo->m_PortNumber;
2420
2421 return STATUS_SUCCESS;
2422}
2423
2424/* Fields not written stay as the child hub set them; HubFlags is OR'ed into */
2425static
2426VOID
2427NTAPI
2429 _In_ HubPdo* Pdo,
2431{
2432 HubChild* Child = Pdo->m_Child;
2433 HubFdo* Hub = Pdo->m_Hub;
2434 const HubParentInfo* Mine = &Hub->m_ParentInfo;
2435
2436 Info->RootHubPdo = Mine->RootHubPdo;
2437 Info->DeviceDescriptor = Child->m_DeviceDescriptor;
2438 Info->U1ExitLatency = Child->m_U1ExitLatency;
2439 Info->U2ExitLatency = Child->m_U2ExitLatency;
2440 Info->SublinkSpeedAttr = Child->m_SublinkSpeedAttr;
2441 Info->SublinkSpeedAttrCount = Child->m_SublinkSpeedAttrCount;
2442 Info->TotalHubDepth = (UCHAR)Child->m_Port->m_Info.TotalHubDepth;
2443 Info->HostInitiatedU1ExitLatency = Child->m_HostU1ExitLatency;
2444 Info->HostInitiatedU2ExitLatency = Child->m_HostU2ExitLatency;
2445 Info->TotalTpPropagationDelay = Mine->TotalTpPropagationDelay +
2447 Child->m_TxTpDelay;
2448
2449 if (Child->m_SlowestLinkU1)
2450 {
2451 Info->SlowestLinkU1ExitLatency = Child->m_Sel.U1Pel;
2452 Info->SlowestLinkU1Depth = Hub->m_Parent.HubDepth;
2453 }
2454 else
2455 {
2456 Info->SlowestLinkU1ExitLatency = Mine->SlowestLinkU1ExitLatency;
2457 Info->SlowestLinkU1Depth = Mine->SlowestLinkU1Depth;
2458 }
2459
2460 if (Child->m_SlowestLinkU2)
2461 {
2462 Info->SlowestLinkU2ExitLatency = Child->m_Sel.U2Pel;
2463 Info->SlowestLinkU2Depth = Hub->m_Parent.HubDepth;
2464 }
2465 else
2466 {
2467 Info->SlowestLinkU2ExitLatency = Mine->SlowestLinkU2ExitLatency;
2468 Info->SlowestLinkU2Depth = Mine->SlowestLinkU2Depth;
2469 }
2470
2471 if (Mine->Flags & HUB_PARENT_DISABLE_LPM)
2472 Info->Flags |= HUB_PARENT_DISABLE_LPM;
2473 if (Child->HasProperty(ChildProperty::HighSpeedCapable))
2475}
2476
2477static
2479NTAPI
2481 _In_ HubPdo* Pdo,
2484{
2485 ULONG Kind = Pdo->m_Child->m_Kind;
2486 const GUID* Type = &Query->CapabilityType;
2488
2489 Query->ResultLength = 0;
2490
2491 DPRINT("Port %u capability query {%08lx-...}\n", Pdo->m_PortNumber, Type->Data1);
2492
2493 if (IsEqualGUID(*Type, GUID_USB_CAPABILITY_FUNCTION_SUSPEND))
2495
2496 if (IsEqualGUID(*Type, GUID_USB_CAPABILITY_STATIC_STREAMS))
2497 {
2498 if (Kind & DSM_KIND_PORT20)
2500
2501 return HubPdoToController(Pdo, Irp);
2502 }
2503
2504 /* Answered here, without output */
2505 if (IsEqualGUID(*Type, GUID_USB_CAPABILITY_SSP_ISOCH_PIPE_FLAGS))
2507
2508 if (IsEqualGUID(*Type, GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE))
2509 Supported = (Kind & DSM_KIND_SUPER_SPEED) != 0;
2510 else if (IsEqualGUID(*Type, GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE))
2515 Supported = TRUE;
2516 else
2517 return HubPdoToController(Pdo, Irp);
2518
2520}
2521
2522/* The one cycle a PDO gets is never given back */
2523static
2525NTAPI
2527 _In_ HubPdo* Pdo,
2529{
2531 {
2532 DPRINT1("Port %u cycle request above passive level\n", Pdo->m_PortNumber);
2534 }
2535
2536 if (InterlockedCompareExchange(&Pdo->m_CycleQueued, 1, 0) == 0)
2537 {
2538 DPRINT1("Client cycles port %u\n", Pdo->m_PortNumber);
2539 Pdo->m_Child->Post(DsmEvent::ClientCyclePort);
2540 }
2541 else
2542 {
2543 DPRINT1("Port %u cycle ignored, one was already requested\n", Pdo->m_PortNumber);
2544 }
2545
2547}
2548
2549/* Unknown codes keep the status the IRP carries (2.0 stack compat) */
2550static
2552NTAPI
2554 _In_ HubPdo* Pdo,
2556{
2558 PVOID Argument1 = Stack->Parameters.Others.Argument1;
2559 HubChild* Child = Pdo->m_Child;
2563 ULONG Code = Stack->Parameters.DeviceIoControl.IoControlCode;
2565
2566 switch (Code)
2567 {
2569 if (!Pdo->HasFlag(PdoFlag::InD0))
2570 {
2571 DPRINT1("Port %u reset refused, the device is not in D0\n", Pdo->m_PortNumber);
2573 }
2575 {
2576 DPRINT1("Port %u reset requested above passive level\n", Pdo->m_PortNumber);
2578 }
2579 return HubPdoQueueAndWait(Pdo, Irp, Pdo->m_Queue);
2580
2582 if (!Pdo->HasFlag(PdoFlag::InD0))
2583 {
2584 DPRINT1("Port %u async reset refused, the device is not in D0\n", Pdo->m_PortNumber);
2586 }
2588 {
2589 DPRINT1("Port %u async reset requested above dispatch level\n", Pdo->m_PortNumber);
2591 }
2592 return HubPdoQueueAsync(Pdo, Irp);
2593
2597 {
2598 DPRINT1("Port %u status request refused, buffer %p\n", Pdo->m_PortNumber, PortStatus);
2600 }
2601
2602 /* The hub machine reads the port and clears ReportPortDisabled through Argument2 */
2603 *PortStatus = 0;
2604 Stack->Parameters.Others.Argument2 = Pdo;
2605 return HubPdoQueueAndWait(Pdo, Irp, WdfDeviceGetDefaultQueue(Pdo->m_Hub->m_Device));
2606
2610
2612 return HubPdoCyclePort(Pdo, Irp);
2613
2615 return HubPdoGetHubName(Pdo, Irp);
2616
2617 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
2618 return HubPdoSubmitIdleRequest(Pdo, Irp);
2619
2620 case IOCTL_INTERNAL_USB_RECORD_FAILURE:
2622
2624 return HubPdoCompleteIrp(Irp, HubQueryDeviceBusInfo(Child, (PUSB_BUS_NOTIFICATION)Argument1));
2625
2627 return HubPdoCompleteIrp(Irp, HubQueryControllerName(Pdo->m_Hub,
2629 (ULONG)(ULONG_PTR)Stack->Parameters.Others.Argument2));
2630
2631 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
2632 if (Argument1 == NULL)
2633 {
2634 DPRINT1("Port %u device handle request has no buffer\n", Pdo->m_PortNumber);
2636 }
2638
2641 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE_EX:
2642 case IOCTL_INTERNAL_USB_GET_TT_DEVICE_HANDLE:
2643 case IOCTL_INTERNAL_USB_NOTIFY_IDLE_READY:
2644 DPRINT1("Port %u internal IOCTL 0x%lx is not supported\n", Pdo->m_PortNumber, Code);
2646
2647 case IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS:
2648 return HubPdoCompleteIrp(Irp, HubPdoTopologyAddress(Pdo, (PUSB_TOPOLOGY_ADDRESS)Argument1));
2649
2650 case IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO:
2651 return HubPdoCompleteIrp(Irp, HubPdoDeviceConfigInfo(Pdo, (PHUB_DEVICE_CONFIG_INFO)Argument1));
2652
2655 Stack->Parameters.Others.Argument2 = Child->m_UsbDevice;
2656 if (Composite != NULL && Composite->CapabilityFlags.CapabilityFunctionSuspend)
2658 return HubPdoToController(Pdo, Irp);
2659
2663 Stack->Parameters.Others.Argument2 = Child->m_UsbDevice;
2664 return HubPdoToController(Pdo, Irp);
2665
2669
2672
2674 Dump = (PUCXHUB_DUMP_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
2675 Dump->Device = Child->m_UsbDevice;
2676 return HubPdoToController(Pdo, Irp);
2677
2679 return HubPdoToController(Pdo, Irp);
2680
2682 ((PUCXHUB_FORWARD_PROGRESS_INFO)Argument1)->Device = Child->m_UsbDevice;
2683 return HubPdoToController(Pdo, Irp);
2684
2685 default:
2686 Status = Irp->IoStatus.Status;
2687 if (!NT_SUCCESS(Status))
2688 DPRINT1("Port %u unknown internal IOCTL 0x%lx completed 0x%lx\n", Pdo->m_PortNumber, Code, Status);
2689 return HubPdoCompleteAsIs(Irp);
2690 }
2691}
2692
2693/* Runs at the caller's IRQL, up to DISPATCH_LEVEL */
2694static
2696NTAPI
2698 _In_ WDFDEVICE Device,
2700{
2701 HubPdo* Pdo = HubGetPdoContext(Device);
2703 ULONG Code = Stack->Parameters.DeviceIoControl.IoControlCode;
2704 PURB Urb = NULL;
2705 BOOLEAN Exempt = FALSE;
2706
2707 switch (Code)
2708 {
2710 Urb = (PURB)Stack->Parameters.Others.Argument1;
2711 Exempt = Urb->UrbHeader.Function == URB_FUNCTION_OPEN_STATIC_STREAMS ||
2712 Urb->UrbHeader.Function == URB_FUNCTION_CLOSE_STATIC_STREAMS;
2713 break;
2714
2717 Exempt = TRUE;
2718 break;
2719
2721 Exempt = Pdo->HasFlag(PdoFlag::InBootPath);
2722 break;
2723
2725 DPRINT("Port %u client says GET_STATUS is unsupported\n", Pdo->m_PortNumber);
2726 Pdo->SetFlag(PdoFlag::FailGetStatus);
2728
2729 default:
2730 break;
2731 }
2732
2733 /* A failed URB carries an invalid parameter status, like the USB 2.0 hub */
2734 if (Pdo->m_FailRequests && !Exempt)
2735 {
2736 DPRINT1("Port %u IRP %p IOCTL 0x%lx failed, the device is not present\n", Pdo->m_PortNumber, Irp, Code);
2737
2738 if (Urb != NULL)
2739 Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
2740
2742 }
2743
2744 if (Urb != NULL)
2745 return HubPdoRouteUrb(Pdo, Irp, Urb);
2746
2747 return HubPdoDispatchIoctl(Pdo, Irp);
2748}
2749
2750/* Device IOCTLs answered by UCX, which expects the device handle stamped in */
2751static
2753NTAPI
2755 _In_ HubPdo* Pdo,
2757 _In_ ULONG Size)
2758{
2760 PUCHAR Buffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
2761 UCXUSBDEVICE UsbDevice = Pdo->m_Child->m_UsbDevice;
2762
2763 if (Stack->Parameters.DeviceIoControl.InputBufferLength != Size ||
2764 Stack->Parameters.DeviceIoControl.OutputBufferLength != Size ||
2765 Buffer == NULL)
2766 {
2767 DPRINT1("Port %u IOCTL 0x%lx buffers %lu/%lu, expected %lu\n",
2768 Pdo->m_PortNumber, Stack->Parameters.DeviceIoControl.IoControlCode,
2769 Stack->Parameters.DeviceIoControl.InputBufferLength,
2770 Stack->Parameters.DeviceIoControl.OutputBufferLength, Size);
2772 }
2773
2775 return HubPdoToController(Pdo, Irp);
2776}
2777
2778static
2780NTAPI
2782 _In_ WDFDEVICE Device,
2784{
2785 HubPdo* Pdo = HubGetPdoContext(Device);
2787
2788 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
2789 {
2796 return HubPdoToController(Pdo, Irp);
2797
2800
2803
2804 default:
2805 return HubPdoPassDown(Device, Irp);
2806 }
2807}
2808
2809/* Default queue: the one request the device machine works on */
2810
2811/* A request that maps to no event fails; only a filter sending straight to the queue gets it here */
2812static
2813VOID
2814NTAPI
2816 _In_ WDFQUEUE Queue,
2817 _In_ WDFREQUEST Request,
2818 _In_ size_t OutputBufferLength,
2819 _In_ size_t InputBufferLength,
2821{
2822 HubPdo* Pdo = HubGetPdoContext(WdfIoQueueGetDevice(Queue));
2823 HubChild* Child = Pdo->m_Child;
2825 PURB Urb;
2827
2830
2831 switch (IoControlCode)
2832 {
2834 Urb = (PURB)Stack->Parameters.Others.Argument1;
2835
2836 switch (Urb->UrbHeader.Function)
2837 {
2838 /* The device handle goes in; an unconfigure drops the handle */
2840 Urb->UrbHeader.UsbdDeviceHandle = Child->m_UsbDevice;
2841 if (Urb->UrbSelectConfiguration.ConfigurationDescriptor == NULL)
2842 {
2843 Urb->UrbSelectConfiguration.ConfigurationHandle = NULL;
2845 }
2846 else
2847 {
2849 }
2850 break;
2851
2854 break;
2855
2857 DPRINT1("Client resets pipe %p on port %u\n", Urb->UrbPipeRequest.PipeHandle, Pdo->m_PortNumber);
2859 break;
2860
2861 case URB_FUNCTION_SYNC_RESET_PIPE:
2862 DPRINT1("Client sync resets pipe %p on port %u\n", Urb->UrbPipeRequest.PipeHandle, Pdo->m_PortNumber);
2864 break;
2865
2866 case URB_FUNCTION_SYNC_CLEAR_STALL:
2867 DPRINT1("Client clears stall on pipe %p on port %u\n", Urb->UrbPipeRequest.PipeHandle, Pdo->m_PortNumber);
2869 break;
2870
2874 break;
2875
2876 default:
2877 break;
2878 }
2879 break;
2880
2883 DPRINT1("Client reset of port %u starts\n", Pdo->m_PortNumber);
2884 Child->m_Port->m_ConnectionStatus = DeviceReset;
2886 break;
2887
2888 default:
2889 break;
2890 }
2891
2892 if (Event == DsmEvent::Count)
2893 {
2894 DPRINT1("Port %u queue got IOCTL 0x%lx it cannot handle\n", Pdo->m_PortNumber, IoControlCode);
2895 WdfRequestComplete(Request, STATUS_NOT_SUPPORTED);
2896 return;
2897 }
2898
2899 DPRINT("Port %u client request %p, IOCTL 0x%lx\n", Pdo->m_PortNumber, Request, IoControlCode);
2900 Child->m_ClientRequest = Request;
2901 Child->Post(Event);
2902}
2903
2904/* Everything else keeps the status the request carries (2.0 compat) */
2905static
2906VOID
2907NTAPI
2909 _In_ WDFQUEUE Queue,
2910 _In_ WDFREQUEST Request,
2911 _In_ size_t OutputBufferLength,
2912 _In_ size_t InputBufferLength,
2914{
2915 PIRP Irp = WdfRequestWdmGetIrp(Request);
2916
2920
2921 switch (IoControlCode)
2922 {
2924 DPRINT("Media serial number request on a USB PDO is not supported\n");
2925 WdfRequestComplete(Request, STATUS_NOT_SUPPORTED);
2926 break;
2927
2928 default:
2929 DPRINT("PDO IOCTL 0x%lx completed 0x%lx\n", IoControlCode, Irp->IoStatus.Status);
2930 WdfRequestComplete(Request, Irp->IoStatus.Status);
2931 break;
2932 }
2933}
2934
2935/* Out of bandwidth notice, a second after UCX ran out */
2936VOID
2937NTAPI
2939 _In_ WDFTIMER Timer)
2940{
2941 HubPort* Port = HubPort::FromObject(WdfTimerGetParentObject(Timer));
2943
2944 /* The timer outlives a device that left the port; only the current one reports */
2945 if (Child == NULL || Child->m_BandwidthRetryTimer != Timer)
2946 return;
2947
2948 DPRINT1("Port %u ran out of bandwidth\n", Port->Number());
2949 HubWmiNotifyInsufficientBandwidth(Port->m_Hub, Port->Number());
2950}
2951
2952/* UCX calls this only while a transfer of the device is pending, so the device is alive */
2953VOID
2954NTAPI
2956 _In_ UCXHUB_HUB_CONTEXT HubContext,
2957 _In_ UCXHUB_DEVICE_CONTEXT DeviceContext)
2958{
2960
2961 DPRINT1("Device %p did not answer a ping\n", DeviceContext);
2963}
2964
2965/* PDO creation */
2966
2968static
2970NTAPI
2971HubPdoAssignPreprocess(
2973{
2974 static UCHAR PnpMinors[] =
2975 {
2985 };
2986 static UCHAR PowerMinors[] = { IRP_MN_SET_POWER };
2988
2989 PAGED_CODE();
2990
2991 Status = WdfDeviceInitAssignWdmIrpPreprocessCallback(Init,
2994 NULL,
2995 0);
2996 if (!NT_SUCCESS(Status))
2997 return Status;
2998
2999 Status = WdfDeviceInitAssignWdmIrpPreprocessCallback(Init,
3001 IRP_MJ_PNP,
3002 PnpMinors,
3003 RTL_NUMBER_OF(PnpMinors));
3004 if (!NT_SUCCESS(Status))
3005 return Status;
3006
3007 Status = WdfDeviceInitAssignWdmIrpPreprocessCallback(Init,
3010 PowerMinors,
3011 RTL_NUMBER_OF(PowerMinors));
3012 if (!NT_SUCCESS(Status))
3013 return Status;
3014
3015 /* Device IOCTLs that go to UCX */
3016 return WdfDeviceInitAssignWdmIrpPreprocessCallback(Init,
3019 NULL,
3020 0);
3021}
3022
3024static
3025VOID
3026NTAPI
3029{
3031 WDF_PDO_EVENT_CALLBACKS PdoEvents;
3032
3033 PAGED_CODE();
3034
3047 WdfDeviceInitSetPnpPowerEventCallbacks(Init, &PnpPower);
3048
3049 WDF_PDO_EVENT_CALLBACKS_INIT(&PdoEvents);
3054 WdfPdoInitSetEventCallbacks(Init, &PdoEvents);
3055}
3056
3057/* Steps that hand the device a WDFDEVICE name; collisions just try the next number */
3059static
3061NTAPI
3062HubPdoCreateNamed(
3064 _Out_ WDFDEVICE* Device)
3065{
3066 /* SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R: SYSTEM all, Administrators read/write/execute,
3067 * Everyone read/write, restricted code read only */
3068 DECLARE_CONST_UNICODE_STRING(Sddl, L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGW;;;WD)(A;;GR;;;RC)");
3070 WCHAR Buffer[32];
3074
3075 PAGED_CODE();
3076
3077 Status = WdfDeviceInitAssignSDDLString(*Init, &Sddl);
3078 if (!NT_SUCCESS(Status))
3079 return Status;
3080
3082 Attributes.EvtCleanupCallback = HubPdoEvtCleanup;
3083
3084 for (Index = 0;; Index++)
3085 {
3086 Status = RtlStringCchPrintfW(Buffer, RTL_NUMBER_OF(Buffer), L"\\Device\\USBPDO-%d", Index);
3087 if (!NT_SUCCESS(Status))
3088 return Status;
3089
3091 Status = WdfDeviceInitAssignName(*Init, &Name);
3092 if (!NT_SUCCESS(Status))
3093 return Status;
3094
3095 Status = WdfDeviceCreate(Init, &Attributes, Device);
3097 return Status;
3098
3099 DPRINT("PDO name %wZ is taken, trying the next\n", &Name);
3100 }
3101}
3102
3104static
3106NTAPI
3107HubPdoAddInterfaces(
3108 _In_ HubPdo* Pdo)
3109{
3111 PNP_LOCATION_INTERFACE Location;
3113 HubChild* Child = Pdo->m_Child;
3115
3116 PAGED_CODE();
3117
3118 if (Child->HasProperty(ChildProperty::IsHub))
3119 {
3120 RtlZeroMemory(&Parent, sizeof(Parent));
3121 Parent.Header.Size = sizeof(Parent);
3122 Parent.Header.Version = UCXHUB_PARENT_INTERFACE_VERSION;
3123 Parent.Header.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
3124 Parent.Header.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
3125 Parent.HubDepth = Pdo->m_Hub->m_Parent.HubDepth + 1;
3126 Parent.HubSpeed = Child->Speed();
3127 Parent.IsEnhancedSuperSpeed = HubPdoIsEnhancedSuperSpeed(Child);
3128 Parent.Hub = Child->m_UsbDevice;
3129
3132 &GUID_UCXHUB_PARENT_INTERFACE,
3134 Config.ImportInterface = TRUE;
3135
3136 Status = WdfDeviceAddQueryInterface(Pdo->m_Device, &Config);
3137 if (!NT_SUCCESS(Status))
3138 return Status;
3139 }
3140
3141 RtlZeroMemory(&Location, sizeof(Location));
3142 Location.Size = sizeof(Location);
3144 Location.Context = Child;
3147 Location.GetLocationString = HubPdoGetLocationString;
3148
3149 WDF_QUERY_INTERFACE_CONFIG_INIT(&Config, (PINTERFACE)&Location, &GUID_PNP_LOCATION_INTERFACE, NULL);
3150 return WdfDeviceAddQueryInterface(Pdo->m_Device, &Config);
3151}
3152
3154static
3156NTAPI
3157HubPdoCreateQueue(
3158 _In_ HubPdo* Pdo)
3159{
3161
3162 PAGED_CODE();
3163
3165 Config.PowerManaged = WdfFalse;
3166 Config.EvtIoInternalDeviceControl = HubPdoEvtIoInternalDeviceControl;
3167 Config.EvtIoDeviceControl = HubPdoEvtIoDeviceControl;
3168
3169 return WdfIoQueueCreate(Pdo->m_Device, &Config, WDF_NO_OBJECT_ATTRIBUTES, &Pdo->m_Queue);
3170}
3171
3173static
3174VOID
3175NTAPI
3177 _In_ HubPdo* Pdo)
3178{
3180 HubChild* Child = Pdo->m_Child;
3181
3182 PAGED_CODE();
3183
3186 Caps.UniqueID = (Child->m_SerialNumber != NULL) ? WdfTrue : WdfFalse;
3188 Caps.Address = Pdo->m_PortNumber;
3189 Caps.UINumber = MAXULONG;
3190 WdfDeviceSetPnpCapabilities(Pdo->m_Device, &Caps);
3191}
3192
3193/* Hubs always claim wake to pass on their children's wake; non wake devices get D2 up to SystemWake */
3195static
3197NTAPI
3198HubPdoSetPowerCapabilities(
3199 _In_ HubPdo* Pdo)
3200{
3203 HubChild* Child = Pdo->m_Child;
3204 SYSTEM_POWER_STATE SystemWake = Pdo->m_Hub->m_Capabilities.SystemWake;
3205 BOOLEAN Wake;
3206 ULONG State;
3207
3208 PAGED_CODE();
3209
3210 Wake = Child->HasProperty(ChildProperty::RemoteWakeCapable) || Child->HasProperty(ChildProperty::IsHub);
3211
3213 Caps.SystemWake = SystemWake;
3216 Caps.DeviceState[State] = (State <= (ULONG)SystemWake) ? PowerDeviceD2 : PowerDeviceD3;
3217
3219 Caps.WakeFromD0 = WdfTrue;
3220 Caps.WakeFromD1 = Wake ? WdfTrue : WdfFalse;
3221 Caps.WakeFromD2 = Wake ? WdfTrue : WdfFalse;
3222 Caps.WakeFromD3 = WdfFalse;
3223 Caps.DeviceD1 = Wake ? WdfTrue : WdfFalse;
3224 Caps.DeviceD2 = Wake ? WdfTrue : WdfFalse;
3225 Caps.D1Latency = 0;
3226 Caps.D2Latency = 0;
3227 Caps.D3Latency = 0;
3228 WdfDeviceSetPowerCapabilities(Pdo->m_Device, &Caps);
3229
3230 if (!Wake || !(Child->m_Kind & DSM_KIND_SUPER_SPEED))
3231 return STATUS_SUCCESS;
3232
3234 Attributes.ParentObject = Pdo->m_Device;
3235
3236 return WdfRequestCreate(&Attributes, WdfDeviceGetIoTarget(Pdo->m_Hub->m_Device), &Pdo->m_WakeRequest);
3237}
3238
3240static
3241VOID
3242NTAPI
3244{
3246
3247 PAGED_CODE();
3248
3250 return;
3251
3252 RtlInitUnicodeString(&Name, L"PoSetSystemWakeDevice");
3255}
3256
3257/* On failure the PDO is deleted once and its cleanup skips the device machine */
3259static
3260BOOLEAN
3261NTAPI
3262HubPdoCreate(
3265{
3266 HubFdo* Hub = Child->m_Hub;
3267 HubPort* Port = Child->m_Port;
3270 WDFDEVICE Device = NULL;
3272 HubPdo* Pdo;
3274
3275 PAGED_CODE();
3276
3278
3280 {
3282 }
3283 else
3284 {
3285 Child->ClearState(ChildState::WorkingDevice);
3286 DPRINT1("Port %u device failed enumeration, creating a placeholder PDO\n", Port->Number());
3287
3288 /* The "device not recognized" popup, except for fixed ports ACPI describes */
3290 HubWmiNotifyEnumerationFailure(Hub, Port->Number());
3291 }
3292
3293 Init = WdfPdoInitAllocate(Hub->m_Device);
3294 if (Init == NULL)
3295 {
3296 DPRINT1("No PDO init for port %u\n", Port->Number());
3297 return FALSE;
3298 }
3299
3303
3304 Status = HubPdoAssignPreprocess(Init);
3305 if (!NT_SUCCESS(Status))
3306 goto Failed;
3307
3309
3310 /* Some clients keep the PDO referenced and send I/O after remove */
3313
3314 Status = HubIdAssignPdoIds(Child, Init);
3315 if (!NT_SUCCESS(Status))
3316 goto Failed;
3317
3318 /* Lets the null driver start a failed device so it can be invalidated later */
3319 if (!Known)
3320 {
3321 Status = WdfPdoInitAssignRawDevice(Init, &HubClassUnknown);
3322 if (!NT_SUCCESS(Status))
3323 DPRINT1("Raw device assignment failed 0x%lx\n", Status);
3324 }
3325
3327 Referenced = TRUE;
3328
3329 Status = HubPdoCreateNamed(&Init, &Device);
3330 if (!NT_SUCCESS(Status))
3331 goto Failed;
3332
3333 /* The cleanup callback owns the device reference from here on */
3334 Referenced = FALSE;
3335
3336 Pdo = new (HubGetPdoContext(Device)) HubPdo();
3338 Pdo->m_Hub = Hub;
3339 Pdo->m_Child = Child;
3340 Pdo->m_PortNumber = Port->Number();
3341 Pdo->m_WdfPowerState = WdfPowerDeviceD3Final;
3342 Pdo->m_ClientContractVersion = HUB_PDO_CONTRACT_UNKNOWN;
3344
3345 /* Bus filters may still send I/O to a placeholder */
3346 if (Known)
3347 Pdo->m_ControllerTarget = Hub->m_ParentInfo.RootHubPdo;
3348 else
3349 Pdo->m_FailRequests = TRUE;
3350
3351 Status = HubPdoAddInterfaces(Pdo);
3352 if (!NT_SUCCESS(Status))
3353 goto Failed;
3354
3359
3360 Child->m_Pdo = Pdo;
3361
3362 Status = HubPdoCreateQueue(Pdo);
3363 if (!NT_SUCCESS(Status))
3364 goto Failed;
3365
3367
3368 Status = HubPdoSetPowerCapabilities(Pdo);
3369 if (!NT_SUCCESS(Status))
3370 goto Failed;
3371
3372 Pdo->m_Idle.Initialize(Pdo);
3373 Status = HubPdoCreateIdleWorkItem(Pdo);
3374 if (!NT_SUCCESS(Status))
3375 goto Failed;
3376
3377 Pdo->m_Idle.Post(IdleEvent::Start, NULL);
3379
3380 Status = WdfFdoAddStaticChild(Hub->m_Device, Device);
3381 if (!NT_SUCCESS(Status))
3382 goto Failed;
3383
3384 Pdo->m_Reported = TRUE;
3385
3388
3389 DPRINT1("Child PDO %p for port %u, VID %04x PID %04x\n",
3390 Device, Pdo->m_PortNumber, Child->m_DeviceDescriptor.idVendor, Child->m_DeviceDescriptor.idProduct);
3391 return TRUE;
3392
3394 DPRINT1("Child PDO creation on port %u failed 0x%lx\n", Port->Number(), Status);
3395
3396 if (Init != NULL)
3397 WdfDeviceInitFree(Init);
3398
3399 if (Device != NULL)
3400 {
3401 Child->m_Pdo = NULL;
3403 }
3404
3407
3408 return FALSE;
3409}
3410
3411/* Serialized client requests */
3412
3413static
3414PURB
3415NTAPI
3417 _In_ WDFREQUEST Request,
3419{
3421
3422 *IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
3424 return NULL;
3425
3426 return (PURB)Stack->Parameters.Others.Argument1;
3427}
3428
3429/* Legacy client behavior for failed selects */
3430static
3431VOID
3432NTAPI
3436{
3437 if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_INTERFACE)
3438 {
3440 Urb->UrbSelectInterface.Interface.InterfaceHandle = (USBD_INTERFACE_HANDLE)(LONG_PTR)-1;
3441 }
3442 else if (Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION)
3443 {
3444 Urb->UrbSelectConfiguration.ConfigurationHandle = NULL;
3445 }
3446}
3447
3448static
3449WDFREQUEST
3450NTAPI
3453{
3454 WDFREQUEST Request = Child->m_ClientRequest;
3455
3456 Child->m_ClientRequest = NULL;
3457 Child->ClearState(ChildState::ActivityIdSet);
3458 return Request;
3459}
3460
3461VOID
3463{
3465 HubPdo* Pdo = Child->m_Pdo;
3466 WDFREQUEST Request = Child->m_ClientRequest;
3470 BOOLEAN ProgrammingLost;
3471 PURB Urb;
3472 ULONG Code;
3473
3475
3476 if (Urb != NULL)
3477 {
3478 if ((Urb->UrbHeader.Function == URB_FUNCTION_SELECT_CONFIGURATION &&
3479 Urb->UrbSelectConfiguration.ConfigurationDescriptor != NULL) ||
3480 Urb->UrbHeader.Function == URB_FUNCTION_SELECT_INTERFACE)
3481 {
3482 Child->SetState(ChildState::ConfigurationValid);
3483 }
3484 }
3486 {
3487 Stack = IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(Request));
3488 Flags = (PUCXHUB_RESET_FLAGS)Stack->Parameters.Others.Argument1;
3489 PowerLost = Pdo->TestAndClearFlag(PdoFlag::PowerLostOnReset);
3490 ProgrammingLost = Pdo->TestAndClearFlag(PdoFlag::ProgrammingLostOnReset);
3491
3492 if (Flags != NULL)
3493 {
3494 Flags->AsUlong = 0;
3495 Flags->PortPowerInterrupted = PowerLost;
3496 Flags->HostContextLost = ProgrammingLost;
3497 }
3498 }
3499
3501 Child->m_Port->m_ConnectionStatus = DeviceConnected;
3502 DPRINT("Port %u client request %p done\n", Pdo->m_PortNumber, Request);
3503 WdfRequestComplete(Request, STATUS_SUCCESS);
3504}
3505
3506VOID
3508{
3510 WDFREQUEST Request = HubTakeClientRequest(Child);
3511 PURB Urb;
3512 ULONG Code;
3513
3515 if (Urb != NULL)
3516 {
3517 Urb->UrbHeader.Status = HubNtStatusToUsbd(STATUS_UNSUCCESSFUL);
3519 }
3520
3521 DPRINT1("Port %u client request %p IOCTL 0x%lx failed\n", Child->m_Port->Number(), Request, Code);
3522 WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
3523}
3524
3525VOID
3527{
3530 WDFREQUEST Request;
3531 PURB Urb;
3532 ULONG Code;
3533
3536 if (Urb != NULL)
3537 {
3538 Urb->UrbHeader.Status = Child->m_LastUsbdStatus;
3540 }
3541
3542 Child->m_LastNtStatus = STATUS_SUCCESS;
3543 Child->m_LastUsbdStatus = USBD_STATUS_SUCCESS;
3544
3545 /* Only reached on failure, so a recorded success must not complete the request as one */
3546 if (NT_SUCCESS(Status))
3548
3549 DPRINT1("Port %u client request %p IOCTL 0x%lx failed 0x%lx, URB status 0x%lx\n",
3550 Child->m_Port->Number(),
3552 Urb != NULL ? Urb->UrbHeader.Status : USBD_STATUS_SUCCESS);
3553 WdfRequestComplete(Request, Status);
3554}
3555
3556/* The request pointer and the URB status are left as they are */
3557VOID
3559{
3560 DPRINT1("Port %u client request %p failed\n", m_Device->m_Port->Number(), m_Device->m_ClientRequest);
3561 WdfRequestComplete(m_Device->m_ClientRequest, STATUS_UNSUCCESSFUL);
3562 m_Device->ClearState(ChildState::ActivityIdSet);
3563}
3564
3565/* Configuration checks for SELECT_CONFIGURATION and SELECT_INTERFACE */
3566
3567static
3569NTAPI
3573{
3575 volatile UCHAR Touch;
3576
3577 if (Descriptor->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE ||
3578 Descriptor->bLength < sizeof(*Descriptor) ||
3579 Descriptor->wTotalLength == 0)
3580 {
3582 }
3583
3584 /* A bad client buffer faults here rather than deep in the validator */
3585 Touch = ((volatile UCHAR*)Descriptor)[0];
3586 Touch = ((volatile UCHAR*)Descriptor)[Descriptor->wTotalLength - 1];
3587 (VOID)Touch;
3588
3590 Child->m_DeviceDescriptor.bcdUSB,
3591 Child->Speed(),
3593 Child->m_Port->m_Info.SspIsochBurstCount,
3594 Child->m_ValidationBits);
3595
3598
3599 return USBD_STATUS_SUCCESS;
3600}
3601
3602static
3603BOOLEAN
3604NTAPI
3608{
3609 Child->m_LastUsbdStatus = UsbdStatus;
3610 Child->m_LastNtStatus = HubUsbdStatusToNt(UsbdStatus);
3611 DPRINT1("Port %u client select check failed, USBD status 0x%lx\n", Child->m_Port->Number(), UsbdStatus);
3612 return FALSE;
3613}
3614
3615/* SuperSpeed devices are measured in 2 mA units against the USB 2.0 budget */
3616BOOLEAN
3618{
3620 HubPdo* Pdo = Child->m_Pdo;
3621 HubFdo* Hub = Child->m_Hub;
3622 ULONG Code;
3623 PURB Urb = HubClientUrb(Child->m_ClientRequest, &Code);
3624 PUSB_CONFIGURATION_DESCRIPTOR Descriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
3625 PUCHAR Entry;
3626 PUCHAR End;
3629 ULONG Count = 0;
3630
3631 PAGED_CODE();
3632
3633 if (Descriptor == NULL)
3634 {
3635 Pdo->m_ConfigPowerDraw = 0;
3636 return TRUE;
3637 }
3638
3642
3643 Pdo->m_ConfigPowerDraw = Descriptor->MaxPower * 2;
3644 if (!Hub->IsRootHub() && Pdo->m_ConfigPowerDraw > Hub->m_MaxPortPower)
3645 {
3646 DPRINT1("Port %u configuration needs %lu mA, the port has %lu mA\n",
3647 Pdo->m_PortNumber, Pdo->m_ConfigPowerDraw, Hub->m_MaxPortPower);
3648 Child->m_LastNtStatus = STATUS_INSUFFICIENT_RESOURCES;
3649 Child->m_LastUsbdStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
3650 Child->m_Port->m_ConnectionStatus = DeviceNotEnoughPower;
3651 HubWmiNotifyInsufficientPower(Hub, Pdo->m_PortNumber);
3652 return FALSE;
3653 }
3654
3655 /* SuperSpeed units are 8 mA with a 150 or 900 mA budget; only reported, for compatibility */
3656 if ((Child->m_Kind & DSM_KIND_SUPER_SPEED) &&
3657 (ULONG)Descriptor->MaxPower * 8 > (Hub->m_MaxPortPower == 100 ? 150UL : 900UL))
3658 {
3659 DPRINT1("Port %u SuperSpeed configuration asks for more power than the port has\n", Pdo->m_PortNumber);
3660 }
3661
3662 Entry = (PUCHAR)&Urb->UrbSelectConfiguration.Interface;
3663 End = (PUCHAR)Urb + Urb->UrbHeader.Length;
3664
3665 while (Entry + sizeof(USHORT) < End && Count < Descriptor->bNumInterfaces)
3666 {
3668 if (Interface->Length < FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) ||
3669 Entry + Interface->Length > End)
3670 {
3671 DPRINT1("Port %u select config interface %lu has bad length %u\n",
3672 Pdo->m_PortNumber, Count, Interface->Length);
3673 Child->m_LastNtStatus = STATUS_UNSUCCESSFUL;
3675 return FALSE;
3676 }
3677
3678 Count++;
3679 Entry += Interface->Length;
3680 }
3681
3682 if (Descriptor->bNumInterfaces == 0 || Count != Descriptor->bNumInterfaces)
3684
3685 return TRUE;
3686}
3687
3688/* NULL unless the interface and all the endpoints it announces are in the configuration */
3689static
3691NTAPI
3695 _In_ UCHAR Alternate)
3696{
3698 PUCHAR End;
3702 BOOLEAN NumberSeen = FALSE;
3703 ULONG Endpoints = 0;
3704
3705 if (Config->bLength < sizeof(*Config) ||
3706 Config->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE ||
3707 Config->wTotalLength < sizeof(*Config))
3708 {
3709 return NULL;
3710 }
3711
3712 End = Position + Config->wTotalLength;
3713
3714 for (; Position + sizeof(*Common) <= End; Position += Common->bLength)
3715 {
3717 if (Common->bLength == 0 || Position + Common->bLength > End)
3718 break;
3719
3721 {
3722 if (Common->bLength < sizeof(*Interface))
3723 continue;
3724
3726 if (Interface->bInterfaceNumber != Number)
3727 {
3728 if (NumberSeen)
3729 break;
3730 continue;
3731 }
3732
3733 NumberSeen = TRUE;
3734 if (Found != NULL)
3735 break;
3736 if (Interface->bAlternateSetting == Alternate)
3737 Found = Interface;
3738 }
3739 else if (Common->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE && Found != NULL)
3740 {
3741 if (Common->bLength < sizeof(USB_ENDPOINT_DESCRIPTOR))
3742 return NULL;
3743 Endpoints++;
3744 }
3745 }
3746
3747 if (Found != NULL && Found->bNumEndpoints > Endpoints)
3748 return NULL;
3749
3750 return Found;
3751}
3752
3753/* A missing interface sets the client's Length to 0; bad pipe flags still fill every pipe */
3754static
3756NTAPI
3760{
3765 ULONG Needed;
3766 ULONG Index;
3767
3768 Descriptor = HubFindSelectedInterface(Config, Info->InterfaceNumber, Info->AlternateSetting);
3769 if (Descriptor == NULL)
3770 {
3771 Info->Length = 0;
3773 }
3774
3775 Needed = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
3776 Descriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION);
3777
3778 if (Info->Length < Needed)
3779 {
3780 Info->Length = (USHORT)Needed;
3782 }
3783
3784 Info->Class = Descriptor->bInterfaceClass;
3785 Info->SubClass = Descriptor->bInterfaceSubClass;
3786 Info->Protocol = Descriptor->bInterfaceProtocol;
3787 Info->Reserved = 0;
3788 Info->InterfaceHandle = NULL;
3789 Info->NumberOfPipes = Descriptor->bNumEndpoints;
3790
3792 for (Index = 0; Index < Descriptor->bNumEndpoints; Index++)
3793 {
3794 /* HubFindSelectedInterface proved this many endpoints follow */
3795 do
3796 {
3798 } while (((PUSB_COMMON_DESCRIPTOR)Position)->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE);
3799
3800 Pipe = &Info->Pipes[Index];
3801 Pipe->EndpointAddress = ((PUSB_ENDPOINT_DESCRIPTOR)Position)->bEndpointAddress;
3802 Pipe->Interval = ((PUSB_ENDPOINT_DESCRIPTOR)Position)->bInterval;
3803 Pipe->PipeType = UsbdPipeTypeControl;
3804 Pipe->PipeHandle = NULL;
3805
3806 if (Pipe->PipeFlags & ~USBD_PF_VALID_MASK)
3808
3809 if (!(Pipe->PipeFlags & USBD_PF_CHANGE_MAX_PACKET))
3810 Pipe->MaximumPacketSize = 0;
3811 }
3812
3813 Info->Length = (USHORT)Needed;
3814 return Status;
3815}
3816
3817/* A NULL handle from an old style client fails when nothing is configured */
3818BOOLEAN
3820{
3822 HubPdo* Pdo = Child->m_Pdo;
3823 HubConfiguration* Current = Child->m_CurrentConfig;
3824 ULONG Code;
3825 PURB Urb = HubClientUrb(Child->m_ClientRequest, &Code);
3826 struct _URB_SELECT_INTERFACE* Select = &Urb->UrbSelectInterface;
3830
3831 /* Clients that never declared a USBD contract (pre Windows 8 style), like a buggy KMDF usbser filter, send no handle */
3832 if (Handle == NULL && Pdo->m_ClientContractVersion == HUB_PDO_CONTRACT_UNKNOWN && Current != NULL)
3833 {
3834 DPRINT1("Select interface without a configuration handle\n");
3836 Select->ConfigurationHandle = Handle;
3837 }
3838
3841
3843
3844 /* Clients commonly get the URB length wrong */
3845 Expected = (USHORT)(Select->Interface.Length + sizeof(struct _URB_HEADER) + sizeof(PVOID));
3846 if (Select->Hdr.Length != Expected)
3847 Select->Hdr.Length = Expected;
3848
3849 UsbdStatus = HubInitInterfaceInformation(&Current->Descriptor, &Select->Interface);
3852
3853 return TRUE;
3854}
3855
3856BOOLEAN
3858{
3860 HubConfiguration* Config = Child->m_CurrentConfig;
3861 ULONG Code;
3862 PURB Urb = HubClientUrb(Child->m_ClientRequest, &Code);
3863 HubPipe* Pipe;
3864
3865 Pipe = HubFindPipeByHandle(Config, Urb->UrbPipeRequest.PipeHandle);
3866 if (Pipe != NULL)
3867 {
3868 Child->m_TargetPipe = Pipe;
3869 return TRUE;
3870 }
3871
3872 DPRINT1("Port %u client pipe handle %p not found\n", Child->m_Port->Number(), Urb->UrbPipeRequest.PipeHandle);
3873 Child->m_LastUsbdStatus = USBD_STATUS_INVALID_PIPE_HANDLE;
3874 Child->m_LastNtStatus = STATUS_INVALID_PARAMETER;
3875 return FALSE;
3876}
3877
3878BOOLEAN
3880{
3882}
3883
3884BOOLEAN
3886{
3888}
3889
3890/* PDO creation and reporting */
3891
3892BOOLEAN
3894{
3896
3897 PAGED_CODE();
3898
3899 Child->m_EnumMessageId = 0;
3900
3901 if (!HubPdoCreate(Child, TRUE))
3902 {
3903 Child->m_Port->m_ConnectionStatus = DeviceGeneralFailure;
3904 return FALSE;
3905 }
3906
3907 HubChildSetPdo(Child, WdfDeviceWdmGetDeviceObject(Child->m_Pdo->m_Device));
3908 Child->m_Port->m_ConnectionStatus = DeviceConnected;
3909 return TRUE;
3910}
3911
3912BOOLEAN
3914{
3915 PAGED_CODE();
3916
3918 return HubPdoCreate(m_Device, FALSE);
3919}
3920
3921VOID
3923{
3925
3926 DPRINT1("Port %u enumeration failed, message %lu\n", Child->m_Port->Number(), Child->m_EnumMessageId);
3927 HubCreateReport(Child->m_Hub->m_Device, HubReport::DeviceEnumerationFailed, Child->m_EnumMessageId);
3928 WdfDeviceSetFailed(Child->m_Pdo->m_Device, WdfDeviceFailedAttemptRestart);
3929}
3930
3931VOID
3933{
3935 KIRQL OldIrql;
3936
3937 DPRINT("Port %u device marked missing\n", m_Device->m_Port->Number());
3938
3940 Status = WdfPdoMarkMissing(m_Device->m_Pdo->m_Device);
3942
3943 if (!NT_SUCCESS(Status))
3944 {
3945 DPRINT1("Marking the PDO missing failed 0x%lx\n", Status);
3947 }
3948}
3949
3950/* A cycle is how UXD redirects the PDO, so its settings stay then */
3951VOID
3953{
3955 HubPdo* Pdo = Child->m_Pdo;
3956
3957 PAGED_CODE();
3958
3959 DPRINT("Port %u device disconnected\n", Pdo->m_PortNumber);
3960
3961 Pdo->SetFlag(PdoFlag::DeviceGone);
3962 Pdo->m_FailRequests = TRUE;
3963
3964 if (!Pdo->HasFlag(PdoFlag::InBootPath) && Pdo->m_CycleQueued == 0)
3965 HubPurgeUxdState(Child, HubUxdEvent::Disconnect);
3966}
3967
3968VOID
3970{
3972
3973 DPRINT("Port %u device reconnected\n", Pdo->m_PortNumber);
3974
3975 Pdo->m_FailRequests = FALSE;
3976 Pdo->ClearFlag(PdoFlag::DeviceGone);
3977}
3978
3979/* Hub power; DISPATCH_LEVEL keeps KMDF from calling a blocking PDO callback on this thread */
3980
3981BOOLEAN
3983{
3985 KIRQL OldIrql;
3986
3990
3991 if (NT_SUCCESS(Status))
3993 else
3994 DPRINT1("Port %u hub power reference failed 0x%lx\n", m_Device->m_Port->Number(), Status);
3995
3996 return TRUE;
3997}
3998
3999VOID
4001{
4002 KIRQL OldIrql;
4003
4005 return;
4006
4010
4012}
4013
4014VOID
4016{
4018}
4019
4020/* PnP waiters */
4021
4022VOID
4024{
4027 m_Device->ClearState(ChildState::ActivityIdSet);
4028}
4029
4030VOID
4032{
4035 m_Device->ClearState(ChildState::ActivityIdSet);
4036}
4037
4038VOID
4040{
4042}
4043
4044VOID
4046{
4048}
4049
4050VOID
4052{
4054}
4055
4056VOID
4058{
4060}
4061
4062/* No string was read, so the text query finds none */
4063VOID
4065{
4067}
4068
4069VOID
4071{
4072 m_Device->m_Port->Post(PortEvent::CycleRequest);
4073}
4074
4075/* PDO flags */
4076
4077VOID
4079{
4081}
4082
4083VOID
4085{
4087}
4088
4089VOID
4091{
4092 m_Device->SetState(ChildState::HotResetOnEnumeration);
4093}
4094
4095VOID
4097{
4098 m_Device->m_Pdo->SetFlag(PdoFlag::PowerLostOnReset);
4099}
4100
4101VOID
4103{
4104 m_Device->m_Pdo->SetFlag(PdoFlag::WasResetAtResume);
4105 m_Device->m_Pdo->SetFlag(PdoFlag::ReportPortDisabled);
4106}
4107
4108VOID
4110{
4111 m_Device->m_Pdo->ClearFlag(PdoFlag::WasResetAtResume);
4112 m_Device->m_Pdo->ClearFlag(PdoFlag::ReportPortDisabled);
4113}
4114
4115BOOLEAN
4117{
4118 return m_Device->m_Pdo->HasFlag(PdoFlag::WasResetAtResume);
4119}
4120
4121BOOLEAN
4123{
4124 return m_Device->m_Pdo != NULL && m_Device->m_Pdo->HasFlag(PdoFlag::Started);
4125}
4126
4127BOOLEAN
4129{
4130 return m_Device->m_Pdo != NULL && m_Device->m_Pdo->HasFlag(PdoFlag::InBootPath);
4131}
4132
4133/* Wake */
4134
4135VOID
4137{
4139}
4140
4141/* KMDF completes the wait wake IRP too early for PoSetSystemWake on it */
4142VOID
4144{
4145 DPRINT("Port %u device is the system wake source\n", m_Device->m_Port->Number());
4146
4148 HubSetSystemWakeDevice(WdfDeviceWdmGetDeviceObject(m_Device->m_Pdo->m_Device));
4149}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
BOOLEAN Expected
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
#define VOID
Definition: acefi.h:82
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
ULONG PortStatus
Definition: bootdev.cpp:131
HubFdo * Hub
Definition: bootdev.cpp:261
return Found
Definition: dirsup.c:1270
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
static NTSTATUS NTAPI HubPdoToController(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:324
static EVT_WDF_DEVICE_D0_EXIT HubPdoEvtD0Exit
Definition: childpdo.cpp:153
static NTSTATUS NTAPI HubPdoSignalCompletion(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
Definition: childpdo.cpp:341
static NTSTATUS NTAPI HubPdoAnswerD3Cold(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:721
#define HUB_START_FAIL_MAX
Definition: childpdo.cpp:53
static NTSTATUS NTAPI HubPdoCompleteAsIs(_Inout_ PIRP Irp)
Definition: childpdo.cpp:300
HubFdo * Hub
Definition: childpdo.cpp:1189
VOID NTAPI HubNoPingResponse(_In_ UCXHUB_HUB_CONTEXT HubContext, _In_ UCXHUB_DEVICE_CONTEXT DeviceContext)
Definition: childpdo.cpp:2955
static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL HubPdoEvtIoDeviceControl
Definition: childpdo.cpp:172
#define HUB_MSOS20_SET_INDEX
Definition: childpdo.cpp:29
static const char HubTagPdo[]
Definition: childpdo.cpp:17
static NTSTATUS NTAPI HubPdoQueueAndWait(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _In_ WDFQUEUE Queue)
Definition: childpdo.cpp:1902
static VOID NTAPI HubPdoStampUrb(_In_ HubPdo *Pdo, _Inout_ PURB Urb)
Definition: childpdo.cpp:1940
static NTSTATUS NTAPI HubPdoPowerIrpComplete(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
Definition: childpdo.cpp:1101
static PFN_HUB_SET_SYSTEM_WAKE_DEVICE HubSetSystemWakeDevice
Definition: childpdo.cpp:149
static NTSTATUS NTAPI HubPdoQueueAsync(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:1929
HubLpmSlot
Definition: childpdo.cpp:131
@ HubLpmPolicy
Definition: childpdo.cpp:136
@ HubLpmU2Timeout
Definition: childpdo.cpp:135
@ HubLpmU2Enable
Definition: childpdo.cpp:133
@ HubLpmU1Enable
Definition: childpdo.cpp:132
@ HubLpmU1Timeout
Definition: childpdo.cpp:134
HubWriteEnumerationData(Child)
USB_ID_STRING FriendlyName
Definition: childpdo.cpp:2328
static VOID NTAPI HubPdoFillHubInfo(_In_ HubPdo *Pdo, _Inout_ HubParentInfo *Info)
Definition: childpdo.cpp:2428
#define HUB_URB_FUNCTION_SELECT_LIKE
Definition: childpdo.cpp:26
static NTSTATUS NTAPI HubPdoRouteUrb(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _Inout_ PURB Urb)
Definition: childpdo.cpp:2153
static const GUID HubCapLowSpeedCompatible
Definition: childpdo.cpp:100
static EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL HubPdoEvtIoInternalDeviceControl
Definition: childpdo.cpp:171
#define HUB_PDO_DRIVER_WAIT_TIME
Definition: childpdo.cpp:20
static PUSB_INTERFACE_DESCRIPTOR NTAPI HubFindSelectedInterface(_In_ PUSB_CONFIGURATION_DESCRIPTOR Config, _In_ UCHAR Number, _In_ UCHAR Alternate)
Definition: childpdo.cpp:3692
static const DEVPROPKEY HubKeyUsb4TunnelState
Definition: childpdo.cpp:108
static EVT_WDF_DEVICE_ENABLE_WAKE_AT_BUS HubPdoEvtEnableWakeAtBus
Definition: childpdo.cpp:161
static const DEVPROPKEY HubKeyBillboardInfo
Definition: childpdo.cpp:104
static PURB NTAPI HubClientUrb(_In_ WDFREQUEST Request, _Out_ PULONG IoControlCode)
Definition: childpdo.cpp:3416
#define HUB_IOCTL_START_TIME_SYNC
Definition: childpdo.cpp:39
static const GUID HubLpmDeviceSettings[HUB_PDO_LPM_SETTINGS]
Definition: childpdo.cpp:112
static EVT_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY HubPdoEvtResourceRequirementsQuery
Definition: childpdo.cpp:164
HubCacheMsOs20SetInfo(Child)
VOID(NTAPI * PFN_HUB_SET_SYSTEM_WAKE_DEVICE)(_In_ PDEVICE_OBJECT DeviceObject)
Definition: childpdo.cpp:146
_Out_ WDFDEVICE * Device
Definition: childpdo.cpp:3065
#define HUB_LPM_POLICY_LINK_BITS
Definition: childpdo.cpp:139
_In_ WDF_POWER_DEVICE_STATE TargetState
Definition: childpdo.cpp:1527
BOOLEAN Referenced
Definition: childpdo.cpp:3271
#define HUB_IOCTL_GET_TRANSPORT_CHARACTERISTICS
Definition: childpdo.cpp:35
_In_ DsmEvent _In_ PCSTR What
Definition: childpdo.cpp:261
static NTSTATUS NTAPI HubPdoSelectLikeComplete(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
Definition: childpdo.cpp:2112
WDF_OBJECT_ATTRIBUTES Attributes
Definition: childpdo.cpp:1190
#define HUB_IOCTL_GET_TIME_SYNC
Definition: childpdo.cpp:40
static PVOID NTAPI HubPdoUrbBuffer(_In_ PVOID Pointer, _In_opt_ PMDL Mdl)
Definition: childpdo.cpp:1986
static BOOLEAN HubSetSystemWakeDeviceResolved
Definition: childpdo.cpp:150
RtlInitEmptyUnicodeString(SymbolicLinkName, NULL, 0)
static EVT_WDF_DEVICE_D0_ENTRY HubPdoEvtD0Entry
Definition: childpdo.cpp:152
static VOID NTAPI HubD3ColdReference(_In_ PVOID Context)
Definition: childpdo.cpp:510
static const GUID HubCapFullSpeedCompatible
Definition: childpdo.cpp:98
static VOID NTAPI HubPdoIndicateWake(_In_ HubPdo *Pdo)
Definition: childpdo.cpp:1598
WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp)
WdfPdoInitAllowForwardingRequestToParent(Init)
static BOOLEAN NTAPI HubFailClientCheck(_In_ HubChild *Child, _In_ USBD_STATUS UsbdStatus)
Definition: childpdo.cpp:3605
static NTSTATUS NTAPI HubPdoForwardSelectLike(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _Inout_ PURB Urb)
Definition: childpdo.cpp:2132
HubPdoPreStart(Pdo->m_Child)
WdfDeviceInitSetDeviceType(Init, FILE_DEVICE_UNKNOWN)
static EVT_WDF_DEVICE_QUERY_REMOVE HubPdoEvtQueryRemove
Definition: childpdo.cpp:160
const SIZE_T Count
Definition: childpdo.cpp:952
static const GUID HubClassUnknown
Definition: childpdo.cpp:94
static BOOLEAN NTAPI HubPdoIsEnhancedSuperSpeed(_In_ HubChild *Child)
Definition: childpdo.cpp:866
#define HUB_DEVICE_CHARACTERISTICS_SIZE
Definition: childpdo.cpp:46
KeClearEvent & Child
Definition: childpdo.cpp:264
static NTSTATUS NTAPI HubPdoQueryCapability(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _Inout_ PUCXHUB_QUERY_CAPABILITY Query)
Definition: childpdo.cpp:2480
#define HUB_STAMPED_HANDLE_OFFSET
Definition: childpdo.cpp:47
HubPdoPostAndWait(Pdo->m_Child, DsmEvent::PdoInstallMsOsExt, "PdoInstallMsOsExt")
static VOID NTAPI HubPatchFailedSelect(_In_ HubChild *Child, _Inout_ PURB Urb)
Definition: childpdo.cpp:3433
PAGED_CODE()
static NTSTATUS NTAPI HubPdoCachedDescriptor(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _Inout_ PURB Urb)
Definition: childpdo.cpp:2000
static VOID NTAPI HubD3ColdDereference(_In_ PVOID Context)
Definition: childpdo.cpp:522
static EVT_WDF_DEVICE_DISABLE_WAKE_AT_BUS HubPdoEvtDisableWakeAtBus
Definition: childpdo.cpp:162
HubPdoResolveSystemWake()
static EVT_WDF_DEVICE_RELEASE_HARDWARE HubPdoEvtReleaseHardware
Definition: childpdo.cpp:155
#define HUB_IOCTL_REGISTER_TRANSPORT_CHANGE
Definition: childpdo.cpp:36
_Outptr_ PZZWSTR * LocationStrings
Definition: childpdo.cpp:950
#define HUB_TRANSPORT_REGISTRATION_SIZE
Definition: childpdo.cpp:45
#define HUB_IOCTL_GET_DEVICE_CHARACTERISTICS
Definition: childpdo.cpp:42
PWCHAR Buffer
Definition: childpdo.cpp:953
return STATUS_SUCCESS
Definition: childpdo.cpp:584
static NTSTATUS NTAPI HubPdoRecordFailure(_In_ HubPdo *Pdo, _In_opt_ HubStartFailHeader *Data)
Definition: childpdo.cpp:2281
HubReadDeviceHardwareValues(Child)
HubPdoRegisterLpmSettings(Pdo)
HubPdoSetCallbacks(Init)
HubPdo * Pdo
Definition: childpdo.cpp:1187
return TRUE
Definition: childpdo.cpp:3391
static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessInternalIoctl
Definition: childpdo.cpp:166
static NTSTATUS NTAPI HubPdoStampAndForward(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _In_ ULONG Size)
Definition: childpdo.cpp:2754
static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubPdoWakeNotificationComplete
Definition: childpdo.cpp:174
static NTSTATUS NTAPI HubPdoCompleteIrp(_Inout_ PIRP Irp, _In_ NTSTATUS Status)
Definition: childpdo.cpp:287
WdfDeviceInitSetExclusive(Init, FALSE)
static NTSTATUS NTAPI HubPdoSendWakeNotification(_In_ HubPdo *Pdo)
Definition: childpdo.cpp:1636
POWER_ACTION Action
Definition: childpdo.cpp:1530
static NTSTATUS NTAPI HubPdoQueryInterface(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:769
#define HUB_IOCTL_UNREGISTER_TRANSPORT_CHANGE
Definition: childpdo.cpp:38
#define HUB_IOCTL_STOP_TIME_SYNC
Definition: childpdo.cpp:41
static NTSTATUS NTAPI HubPdoGetHubName(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:2218
static EVT_WDF_OBJECT_CONTEXT_CLEANUP HubPdoEvtCleanup
Definition: childpdo.cpp:165
#define HUB_IOCTL_NOTIFY_TRANSPORT_CHANGE
Definition: childpdo.cpp:37
#define HUB_URB_FUNCTION_FAST_PATH_2
Definition: childpdo.cpp:25
static USBD_STATUS NTAPI HubInitInterfaceInformation(_In_ PUSB_CONFIGURATION_DESCRIPTOR Config, _Inout_ PUSBD_INTERFACE_INFORMATION Info)
Definition: childpdo.cpp:3757
static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessPnp
Definition: childpdo.cpp:168
static EVT_WDF_WORKITEM HubPdoEvtCompletePowerIrp
Definition: childpdo.cpp:173
ULONG Index
Definition: childpdo.cpp:3073
_Inout_ PIRP Irp
Definition: childpdo.cpp:361
HubPdoSetPnpCapabilities(Pdo)
PWDFDEVICE_INIT Init
Definition: childpdo.cpp:3269
static EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND HubPdoEvtSelfManagedIoSuspend
Definition: childpdo.cpp:158
WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFilePaging, TRUE)
static NTSTATUS NTAPI HubPdoDispatchIoctl(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:2553
WDFDEVICE HubDevice
Definition: childpdo.cpp:989
static EVT_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST HubPdoEvtParentInterfaceQuery
Definition: childpdo.cpp:170
static NTSTATUS NTAPI HubPdoValidateUrb(_Inout_ PURB Urb)
Definition: childpdo.cpp:1951
static NTSTATUS NTAPI HubPdoSyncComplete(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
Definition: childpdo.cpp:1876
USBD_STATUS NTAPI HubNtStatusToUsbd(_In_ NTSTATUS Status)
Definition: childpdo.cpp:190
static EVT_WDF_DEVICE_REPORTED_MISSING HubPdoEvtReportedMissing
Definition: childpdo.cpp:163
#define HUB_IOCTL_MEDIA_SERIAL_NUMBER
Definition: childpdo.cpp:50
static EVT_WDF_DEVICE_SURPRISE_REMOVAL HubPdoEvtSurpriseRemoval
Definition: childpdo.cpp:156
static EVT_WDF_DEVICE_PREPARE_HARDWARE HubPdoEvtPrepareHardware
Definition: childpdo.cpp:154
static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessIoctl
Definition: childpdo.cpp:167
#define HUB_URB_FUNCTION_FAST_PATH_1
Definition: childpdo.cpp:24
NTSTATUS Status
Definition: childpdo.cpp:561
return FALSE
Definition: childpdo.cpp:3408
HubPort * Port
Definition: childpdo.cpp:3267
static NTSTATUS NTAPI HubPdoCyclePort(_In_ HubPdo *Pdo, _Inout_ PIRP Irp)
Definition: childpdo.cpp:2526
static const GUID HubLpmHubSettings[HUB_PDO_LPM_SETTINGS]
Definition: childpdo.cpp:121
static EVT_WDF_DEVICE_QUERY_STOP HubPdoEvtQueryStop
Definition: childpdo.cpp:159
static POWER_SETTING_CALLBACK HubPdoLpmSettingChanged
Definition: childpdo.cpp:175
_In_ BOOLEAN D3ColdSupport
Definition: childpdo.cpp:538
static EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT HubPdoEvtSelfManagedIoStart
Definition: childpdo.cpp:157
WdfDeviceInitSetRemoveLockOptions(Init, &RemoveLock)
static NTSTATUS NTAPI HubPdoMsFeatureDescriptor(_In_ HubPdo *Pdo, _Inout_ PIRP Irp, _Inout_ PURB Urb)
Definition: childpdo.cpp:2062
Info Length
Definition: childpdo.cpp:2346
HubFlushSqmFlags(Child)
WDF_REMOVE_LOCK_OPTIONS RemoveLock
Definition: childpdo.cpp:3268
_In_ BOOLEAN Known
Definition: childpdo.cpp:3265
_In_ DsmEvent Event
Definition: childpdo.cpp:259
static NTSTATUS NTAPI HubPdoTopologyAddress(_In_ HubPdo *Pdo, _Out_opt_ PUSB_TOPOLOGY_ADDRESS Address)
Definition: childpdo.cpp:2401
static WDFREQUEST NTAPI HubTakeClientRequest(_In_ HubChild *Child)
Definition: childpdo.cpp:3451
static USBD_STATUS NTAPI HubCheckConfigDescriptor(_In_ HubChild *Child, _In_ PUSB_CONFIGURATION_DESCRIPTOR Descriptor)
Definition: childpdo.cpp:3570
static const DEVPROPKEY HubKeyDualRoleFeatures
Definition: childpdo.cpp:106
#define HUB_URB_FUNCTION_LAST
Definition: childpdo.cpp:23
const GUID * InterfaceGuid
Definition: childpdo.cpp:1191
static EVT_WDFDEVICE_WDM_IRP_PREPROCESS HubPdoPreprocessSetPower
Definition: childpdo.cpp:169
static NTSTATUS NTAPI HubPdoPassDown(_In_ WDFDEVICE Device, _Inout_ PIRP Irp)
Definition: childpdo.cpp:312
UNICODE_STRING Name
Definition: childpdo.cpp:3071
static NTSTATUS NTAPI HubUsbdStatusToNt(_In_ USBD_STATUS Status)
Definition: childpdo.cpp:220
EVT_WDF_DEVICE_USAGE_NOTIFICATION_EX HubPdoEvtUsageNotificationEx
Definition: childpdo.h:168
#define HUB_PDO_LPM_SETTINGS
Definition: childpdo.h:39
#define HUB_PDO_CONTRACT_UNKNOWN
Definition: childpdo.h:42
@ ProgrammingLostOnReset
@ WasResetAtResume
@ WakeArmRequested
@ QueryStopped
@ ClientDoesFunctionSuspend
@ IdleMachineStarted
@ ReportPortDisabled
@ QueryRemoved
@ FailGetStatus
@ WakeNotificationSent
@ WaitWakePending
Definition: bufpool.h:45
VOID CompletePreStart()
Definition: childpdo.cpp:4045
BOOLEAN CreatePlaceholderPdo()
Definition: childpdo.cpp:3913
VOID MarkPowerLost()
Definition: childpdo.cpp:4096
HubChild * m_Device
Definition: devsm.h:1832
BOOLEAN FindClientPipe()
Definition: childpdo.cpp:3857
BOOLEAN CreatePdo()
Definition: childpdo.cpp:3893
VOID FinishWaitWake()
Definition: childpdo.cpp:4136
VOID MarkSystemWakeSource()
Definition: childpdo.cpp:4143
VOID AckPreStart()
Definition: childpdo.cpp:4051
VOID CyclePortForClient()
Definition: childpdo.cpp:4070
VOID ClearResetAtResume()
Definition: childpdo.cpp:4109
BOOLEAN SelectInterfaceValid()
Definition: childpdo.cpp:3819
VOID FailClientRequest()
Definition: childpdo.cpp:3558
VOID StartDriverWaitTimer()
Definition: childpdo.cpp:4015
BOOLEAN PipeIsIsochronous()
Definition: childpdo.cpp:3885
VOID ReportDeviceMissing()
Definition: childpdo.cpp:3932
VOID NotifyDisconnected()
Definition: childpdo.cpp:3952
BOOLEAN ReferenceHubPower()
Definition: childpdo.cpp:3982
BOOLEAN PipeIsZeroBandwidth()
Definition: childpdo.cpp:3879
VOID CompleteClientRequestFailed()
Definition: childpdo.cpp:3507
VOID AllowIo()
Definition: childpdo.cpp:4078
VOID CompleteClientRequest()
Definition: childpdo.cpp:3462
BOOLEAN PdoStarted()
Definition: childpdo.cpp:4122
VOID DereferenceHubPower()
Definition: childpdo.cpp:4000
BOOLEAN ResetAtResumeMarked()
Definition: childpdo.cpp:4116
VOID SignalPnpWaiter()
Definition: childpdo.cpp:4023
VOID CompleteQueryText()
Definition: childpdo.cpp:4057
VOID ForceResetOnNextStart()
Definition: childpdo.cpp:4090
VOID SignalPnpPowerFailure()
Definition: childpdo.cpp:4031
BOOLEAN SelectConfigValid()
Definition: childpdo.cpp:3617
VOID ReleasePnpWaiter()
Definition: childpdo.cpp:4039
VOID SetFailIo()
Definition: childpdo.cpp:4084
VOID CompleteClientRequestLastStatus()
Definition: childpdo.cpp:3526
BOOLEAN IsBootDevice()
Definition: childpdo.cpp:4128
VOID SignalQueryText()
Definition: childpdo.cpp:4064
VOID NotifyReconnected()
Definition: childpdo.cpp:3969
VOID ReportEnumFailure()
Definition: childpdo.cpp:3922
VOID MarkResetAtResume()
Definition: childpdo.cpp:4102
Definition: Header.h:9
HubPort * m_Port
Definition: hubchild.h:317
VOID ClearState(_In_ ChildState Flag)
Definition: hubchild.h:274
USB_DEVICE_DESCRIPTOR m_DeviceDescriptor
Definition: hubchild.h:386
KEVENT m_PnpEvent
Definition: hubchild.h:341
KEVENT m_PreStartEvent
Definition: hubchild.h:343
WDFREQUEST m_ClientRequest
Definition: hubchild.h:365
BOOLEAN m_HubPowerReferenceHeld
Definition: hubchild.h:538
HubFdo * m_Hub
Definition: hubchild.h:316
NTSTATUS m_LastNtStatus
Definition: hubchild.h:353
HubTimer m_Timer
Definition: hubchild.h:335
HubPipe * m_TargetPipe
Definition: hubchild.h:438
ULONG m_LpmPolicy
Definition: hubchild.h:441
KEVENT m_QueryTextEvent
Definition: hubchild.h:344
HubPdo * m_Pdo
Definition: hubchild.h:318
VOID SetState(_In_ ChildState Flag)
Definition: hubchild.h:267
NTSTATUS m_PnpStatus
Definition: hubchild.h:342
Definition: fdo.h:132
BOOLEAN m_TunneledDevicesSkipU2
Definition: fdo.h:470
WDFDEVICE m_Device
Definition: fdo.h:349
UCXHUB_STACK_INTERFACE m_Stack
Definition: fdo.h:356
BOOLEAN HasFlag(_In_ HubFlag Flag) const
Definition: fdo.h:153
DEVICE_CAPABILITIES m_Capabilities
Definition: fdo.h:359
UCXUSBDEVICE UsbDevice() const
Definition: fdo.h:180
HubParentInfo m_ParentInfo
Definition: fdo.h:360
USB_30_HUB_DESCRIPTOR Usb30
Definition: fdo.h:420
ULONG m_MaxPortPower
Definition: fdo.h:384
UCXHUB_PARENT_INTERFACE m_Parent
Definition: fdo.h:355
BOOLEAN IsRootHub() const
Definition: fdo.h:174
union HubFdo::@1628 m_HubDescriptor
VOID SetFlag(_In_ PdoFlag Flag)
Definition: childpdo.h:73
D3COLD_SUPPORT_INTERFACE m_AcpiD3Cold
Definition: childpdo.h:126
BOOLEAN HasFlag(_In_ PdoFlag Flag) const
Definition: childpdo.h:66
BOOLEAN m_FailRequests
Definition: childpdo.h:95
WDFDEVICE m_Device
Definition: childpdo.h:55
static HubPdo * FromDevice(_In_ WDFDEVICE Device)
Definition: childpdo.cpp:180
VOID ClearFlag(_In_ PdoFlag Flag)
Definition: childpdo.h:80
BOOLEAN HasProperty(_In_ PortProperty Property) const
Definition: hubport.h:206
HubChild * m_Child
Definition: hubport.h:236
static HubPort * FromObject(_In_ WDFOBJECT Object)
Definition: hubport.cpp:30
USHORT m_LastCompanionPort
Definition: hubport.h:275
HubConnectorId m_ConnectorId
Definition: hubport.h:268
USHORT Number() const
Definition: hubport.h:213
VOID Post(_In_ PortEvent Event)
Definition: hubport.h:157
USB_CONNECTION_STATUS m_ConnectionStatus
Definition: hubport.h:254
USHORT m_FirstCompanionPort
Definition: hubport.h:274
HubFdo * m_Hub
Definition: hubport.h:228
VOID Start(_In_ ULONG Milliseconds)
Definition: hubutil.h:104
@ Supported
Definition: classpnp.h:733
UINT Depth
Definition: d3d12.idl:4644
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define Code
Definition: deflate.h:80
BOOLEAN NTAPI HubDescCheckConfiguration(_In_ const HubDescContext *Context, _In_reads_bytes_opt_(Length) PUSB_CONFIGURATION_DESCRIPTOR Descriptor, _In_ ULONG Length, _Out_opt_ PBOOLEAN SupportsStreams)
Definition: desccheck.cpp:1237
VOID NTAPI HubDescInitDeviceContext(_Out_ HubDescContext *Context, _In_ USHORT BcdUsb, _In_ USB_DEVICE_SPEED Speed, _In_ BOOLEAN Win8Behavior, _In_ ULONG SspIsochBurstCount, _In_opt_ PULONG Bitmap)
Definition: desccheck.cpp:91
PUCHAR End
Definition: desccheck.cpp:2229
VOID NTAPI HubFreeBillboardInfo(_In_ HubChild *Child)
Definition: devdesc.cpp:348
_In_ BOOLEAN _In_ ULONG Features
Definition: devdesc.cpp:445
_Inout_ HubConfiguration ** Slot
Definition: devhcd.cpp:1260
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
ULONG Copy
Definition: devhcd.cpp:1449
#define HUB_LPM_POLICY_U1_INITIATE
Definition: devhcd.h:15
#define HUB_LPM_POLICY_U1_ACCEPT
Definition: devhcd.h:13
#define HUB_LPM_POLICY_U2_ENABLED
Definition: devhcd.h:12
#define HUB_LPM_POLICY_U1_ENABLED
Definition: devhcd.h:11
#define HUB_LPM_POLICY_U2_ACCEPT
Definition: devhcd.h:14
#define HUB_LPM_POLICY_U2_INITIATE
Definition: devhcd.h:16
#define HUB_LPM_POLICY_CONSERVATIVE
Definition: devhcd.h:17
#define HUB_LPM_POLICY_AGGRESSIVE
Definition: devhcd.h:18
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
#define DEVPROP_TYPE_UINT32
Definition: devpropdef.h:36
#define DEVPROP_TYPE_BINARY
Definition: devpropdef.h:53
HubPipe *NTAPI HubFindPipeByHandle(_In_opt_ HubConfiguration *Config, _In_ USBD_PIPE_HANDLE Handle)
Definition: devreq.cpp:858
#define DSM_KIND_SUPER_SPEED
Definition: devsm.h:150
DsmEvent
Definition: devsm.h:15
@ ClientSyncResetPipe
@ ClientResetDevice
@ ClientUnconfigure
@ NoPingResponse
@ LpmSettingChanged
@ ClientCyclePort
@ ClientSetInterface
@ ClientClearStall
@ PdoInstallMsOsExt
@ PdoReportedMissing
@ ClientResetPipe
@ PdoPowerDownFinal
@ PdoPrepareHibernate
@ ClientSelectConfig
#define DSM_KIND_FULL_SPEED
Definition: devsm.h:148
#define DSM_KIND_HIGH_SPEED
Definition: devsm.h:147
#define DSM_KIND_PORT20
Definition: devsm.h:152
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
_Check_return_ _In_ ULONG _In_ DEVICE_POWER_STATE DevicePowerState
Definition: dispmprt.h:1274
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define L(x)
Definition: resources.c:13
static VOID Wake(_In_ UCHAR Csn)
Definition: hardware.c:154
switch(r->id)
Definition: btrfs.c:3046
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
HubDriverState HubDriver
Definition: entry.cpp:13
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define PagedPool
Definition: env_spec_w32.h:308
NTSTATUS NTAPI HubCreateReport(_In_ WDFDEVICE HubFdo, _In_ HubReport Type, _In_ ULONG SubReason)
Definition: errreport.cpp:151
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
return pRequest Reuse(ReuseParams)
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:24
_In_ UCXUSBDEVICE UsbDevice
Definition: hostctl.h:31
#define HUB_TUNNEL_STATE_UNKNOWN
Definition: hubchild.h:54
@ D3ColdEnabledByDriver
@ ConfigurationValid
@ UseWin8DescriptorValidation
NTSTATUS NTAPI HubIdBuildCompatibleIds(_In_ HubChild *Child, _In_opt_ PWDFDEVICE_INIT DeviceInit, _Out_opt_ PUSB_ID_STRING Ids)
Definition: hubid.cpp:597
NTSTATUS NTAPI HubIdBuildHardwareIds(_In_ HubChild *Child, _In_opt_ PWDFDEVICE_INIT DeviceInit, _Out_opt_ PUSB_ID_STRING Ids)
Definition: hubid.cpp:381
VOID NTAPI HubIdListFree(_Inout_ PUSB_ID_STRING Ids)
Definition: hubid.cpp:159
NTSTATUS NTAPI HubIdListCopy(_Out_ PUSB_ID_STRING Destination, _In_ const USB_ID_STRING *Source)
Definition: hubid.cpp:173
HubUxdSettings Current
VOID NTAPI USBD_RemoveDeviceFromGlobalList(_In_ PVOID DeviceContext)
Definition: hubsup.c:286
BOOLEAN NTAPI HubUsb4NeedsHostPower(_In_ HubChild *Child)
Definition: hubtunnel.cpp:587
EVT_WDF_TIMER HubEvtBandwidthRetryTimer
Definition: hubsvc.h:214
ULONG Chars
Definition: hubtunnel.cpp:833
WdfWorkItemEnqueue(WorkItem)
#define IOCTL_UCXHUB_RESET_PORT_ASYNC
Definition: hubucx.h:78
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
#define UCXHUB_PARENT_INTERFACE_VERSION
Definition: hubucx.h:493
#define IOCTL_UCXHUB_FREE_DUMP_DATA
Definition: hubucx.h:74
_In_ UCXHUB_DEVICE_CONTEXT DeviceContext
Definition: hubucx.h:237
struct _UCXHUB_DUMP_DEVICE_INFO * PUCXHUB_DUMP_DEVICE_INFO
union _UCXHUB_RESET_FLAGS * PUCXHUB_RESET_FLAGS
_In_ PUNICODE_STRING SymbolicLinkName
Definition: hubucx.h:491
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
Definition: hubucx.h:227
#define IOCTL_UCXHUB_QUERY_USB_CAPABILITY
Definition: hubucx.h:65
#define IOCTL_UCXHUB_SET_FUNCTION_HANDLE_DATA
Definition: hubucx.h:66
#define IOCTL_UCXHUB_GET_DUMP_DATA
Definition: hubucx.h:72
struct _UCXHUB_PARENT_INTERFACE * PUCXHUB_PARENT_INTERFACE
#define IOCTL_UCXHUB_NOTIFY_FORWARD_PROGRESS
Definition: hubucx.h:69
#define IOCTL_UCXHUB_GET_HUB_INFO
Definition: hubucx.h:64
struct _UCXHUB_FORWARD_PROGRESS_INFO * PUCXHUB_FORWARD_PROGRESS_INFO
_In_ UCXUSBDEVICE _In_ PDEVICE_OBJECT Pdo
Definition: hubucx.h:280
#define HUB_TAG_DEVICE
Definition: hubutil.h:13
Name HubName[0]
Definition: hubwmi.cpp:470
_In_ const GUID _In_ ULONG _In_opt_ PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE Query
Definition: hubwmi.cpp:114
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
#define InterlockedOr
Definition: interlocked.h:239
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define C_ASSERT(e)
Definition: intsafe.h:73
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
_In_ PIRP Irp
Definition: kse.h:79
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define Open
Definition: syshdrs.h:62
if(dx< 0)
Definition: linetemp.h:194
static void Dump(LPITEMIDLIST pidl, PCSTR Heading=NULL)
Definition: lnktool.cpp:230
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ NormalPagePriority
Definition: imports.h:54
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define min(a, b)
Definition: monoChain.cc:55
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_In_ PNDIS_STRING _In_ PNDIS_STRING SymbolicName
Definition: ndis.h:4677
_In_ ULONG Number
Definition: haltypes.h:1940
#define KernelMode
Definition: asm.h:38
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Outptr_
Definition: no_sal2.h:262
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define LOCALE_NEUTRAL
#define UNICODE_NULL
_NullNull_terminated_ WCHAR * PZZWSTR
Definition: ntbasedef.h:432
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ NotificationEvent
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
#define IoCompleteRequest
Definition: irp.c:1272
#define IoCallDriver
Definition: irp.c:1257
@ PowerSystemSleeping1
Definition: ntpoapi.h:37
@ PowerSystemShutdown
Definition: ntpoapi.h:41
@ PowerSystemWorking
Definition: ntpoapi.h:36
POWER_ACTION
Definition: ntpoapi.h:122
@ PowerActionNone
Definition: ntpoapi.h:123
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD2
Definition: ntpoapi.h:51
@ PowerDeviceD3
Definition: ntpoapi.h:52
enum _DEVICE_POWER_STATE DEVICE_POWER_STATE
enum _SYSTEM_POWER_STATE SYSTEM_POWER_STATE
#define STATUS_POWER_STATE_INVALID
Definition: ntstatus.h:957
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
#define STRSAFE_FILL_BEHIND_NULL
Definition: ntstrsafe.h:32
NTSTRSAFEVAPI RtlStringCchPrintfExW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd, _Out_opt_ size_t *pcchRemaining, _In_ STRSAFE_DWORD dwFlags, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1246
static BOOL Set
Definition: pageheap.c:10
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define FILE_DEVICE_UNKNOWN
Definition: winioctl.h:79
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
@ Failed
Definition: arc.h:88
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:73
Definition: client.c:31
UCHAR PreferredModeEntry
Definition: childpdo.cpp:69
UCHAR NumberOfAlternateModes
Definition: childpdo.cpp:68
PFN_HUB_UNREGISTER_POWER_SETTING UnregisterPowerSetting
Definition: hubdriver.h:115
PFN_HUB_REGISTER_POWER_SETTING RegisterPowerSetting
Definition: hubdriver.h:114
PDEVICE_OBJECT RootHubPdo
Definition: fdo.h:88
USB_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: fdo.h:89
ULONG Flags
Definition: fdo.h:100
USHORT TotalTpPropagationDelay
Definition: fdo.h:99
UCHAR SlowestLinkU1Depth
Definition: fdo.h:93
UCHAR SlowestLinkU2Depth
Definition: fdo.h:95
USHORT SlowestLinkU2ExitLatency
Definition: fdo.h:94
USHORT SlowestLinkU1ExitLatency
Definition: fdo.h:92
PUSB_ENDPOINT_DESCRIPTOR Descriptor
Definition: hubchild.h:172
BOOLEAN ZeroBandwidth
Definition: hubchild.h:178
NTSTATUS NtStatus
Definition: childpdo.cpp:59
USBD_STATUS UsbdStatus
Definition: childpdo.cpp:60
UCHAR DriverData[4]
Definition: childpdo.cpp:62
PSET_D3COLD_SUPPORT SetD3ColdSupport
Definition: iotypes.h:7574
PINTERFACE_DEREFERENCE InterfaceDereference
Definition: iotypes.h:7573
PINTERFACE_REFERENCE InterfaceReference
Definition: iotypes.h:7572
PGET_LOCATION_STRING GetLocationString
Definition: iotypes.h:4559
PINTERFACE_REFERENCE InterfaceReference
Definition: iotypes.h:4557
PINTERFACE_DEREFERENCE InterfaceDereference
Definition: iotypes.h:4558
COMPOSITE_DEVICE_CAPABILITIES CapabilityFlags
Definition: usbdlib.h:123
USB_DEVICE_SPEED HubSpeed
Definition: hubucx.h:504
USB_TOPOLOGY_ADDRESS HubTopologyAddress
Definition: hubucx.h:514
PFN_UCXHUB_IS_DEVICE_DISCONNECTED IsDeviceDisconnected
Definition: hubucx.h:452
PFN_UCXHUB_CONTROLLER_STOP_IDLE BlockControllerIdle
Definition: hubucx.h:454
PFN_UCXHUB_CONTROLLER_RESUME_IDLE AllowControllerIdle
Definition: hubucx.h:455
struct _URB_HEADER Hdr
Definition: usb.h:314
USBD_INTERFACE_INFORMATION Interface
Definition: usb.h:316
USBD_CONFIGURATION_HANDLE ConfigurationHandle
Definition: usb.h:315
Definition: usb.h:565
USBD_INTERFACE_HANDLE InterfaceHandle
Definition: usb.h:296
WDF_TRI_STATE SurpriseRemovalOK
Definition: wdfdevice.h:1531
DEVICE_POWER_STATE DeviceWake
Definition: wdfdevice.h:1590
SYSTEM_POWER_STATE SystemWake
Definition: wdfdevice.h:1591
DEVICE_POWER_STATE DeviceState[PowerSystemMaximum]
Definition: wdfdevice.h:1584
PFN_WDF_DEVICE_REPORTED_MISSING EvtDeviceReportedMissing
Definition: wdfpdo.h:193
PFN_WDF_DEVICE_ENABLE_WAKE_AT_BUS EvtDeviceEnableWakeAtBus
Definition: wdfpdo.h:181
PFN_WDF_DEVICE_DISABLE_WAKE_AT_BUS EvtDeviceDisableWakeAtBus
Definition: wdfpdo.h:187
PFN_WDF_DEVICE_RESOURCE_REQUIREMENTS_QUERY EvtDeviceResourceRequirementsQuery
Definition: wdfpdo.h:165
PFN_WDF_DEVICE_D0_ENTRY EvtDeviceD0Entry
Definition: wdfdevice.h:1164
PFN_WDF_DEVICE_SELF_MANAGED_IO_RESTART EvtDeviceSelfManagedIoRestart
Definition: wdfdevice.h:1174
PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT EvtDeviceSelfManagedIoInit
Definition: wdfdevice.h:1172
PFN_WDF_DEVICE_QUERY_STOP EvtDeviceQueryStop
Definition: wdfdevice.h:1177
PFN_WDF_DEVICE_QUERY_REMOVE EvtDeviceQueryRemove
Definition: wdfdevice.h:1176
PFN_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND EvtDeviceSelfManagedIoSuspend
Definition: wdfdevice.h:1173
PFN_WDF_DEVICE_D0_EXIT EvtDeviceD0Exit
Definition: wdfdevice.h:1166
PFN_WDF_DEVICE_SURPRISE_REMOVAL EvtDeviceSurpriseRemoval
Definition: wdfdevice.h:1175
PFN_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware
Definition: wdfdevice.h:1168
PFN_WDF_DEVICE_USAGE_NOTIFICATION_EX EvtDeviceUsageNotificationEx
Definition: wdfdevice.h:1180
PFN_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware
Definition: wdfdevice.h:1169
static const VBE_MODE Modes[VBE_MODE_COUNT]
Definition: vbe.c:189
static COORD Position
Definition: mouse.c:34
PVOID NTAPI MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
Definition: sysldr.c:3672
#define STATUS_PENDING
Definition: telnetd.h:14
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
_In_ PGUID _In_ ULONG OutputBufferLength
Definition: ucxcontroller.h:81
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
_In_ UCXUSBDEVICE _In_ ULONG Interface
Definition: ucxusbdevice.h:428
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define USB_CONFIGURATION_DESCRIPTOR_TYPE
Definition: usb100.h:50
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usb100.h:53
struct _USB_INTERFACE_DESCRIPTOR * PUSB_INTERFACE_DESCRIPTOR
#define USB_DEVICE_DESCRIPTOR_TYPE
Definition: usb100.h:49
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
struct _USB_COMMON_DESCRIPTOR * PUSB_COMMON_DESCRIPTOR
struct _USB_ENDPOINT_DESCRIPTOR * PUSB_ENDPOINT_DESCRIPTOR
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usb100.h:52
@ UsbHighSpeed
Definition: usb200.h:44
#define HUB_PARENT_DISABLE_LPM
Definition: fdo.h:106
@ InAcpiNamespace
@ NoSelectiveSuspendIntegrated
@ WakeOnConnect
#define HUB_PARENT_HIGH_SPEED_CAPABLE
Definition: fdo.h:107
struct _USBD_INTERFACE_INFORMATION * PUSBD_INTERFACE_INFORMATION
#define USBD_STATUS_DEVICE_GONE
Definition: usb.h:222
struct _USBD_PIPE_INFORMATION USBD_PIPE_INFORMATION
#define URB_FUNCTION_SELECT_INTERFACE
Definition: usb.h:87
struct _URB * PURB
#define USBD_STATUS_INVALID_PIPE_HANDLE
Definition: usb.h:205
#define USBD_STATUS_CANCELED
Definition: usb.h:225
#define USBD_STATUS_INVALID_PIPE_FLAGS
Definition: usb.h:219
#define USBD_STATUS_SUCCESS
Definition: usb.h:177
PVOID USBD_INTERFACE_HANDLE
Definition: usb.h:243
#define USBD_PF_CHANGE_MAX_PACKET
Definition: usb.h:281
#define USBD_TRANSFER_DIRECTION_IN
Definition: usb.h:167
#define URB_FUNCTION_CONTROL_TRANSFER
Definition: usb.h:94
#define USBD_STATUS_NOT_SUPPORTED
Definition: usb.h:213
#define USBD_STATUS_INSUFFICIENT_RESOURCES
Definition: usb.h:215
#define URB_FUNCTION_SELECT_CONFIGURATION
Definition: usb.h:86
#define USBD_STATUS_INVALID_PARAMETER
Definition: usb.h:203
#define USBD_STATUS_INTERFACE_NOT_FOUND
Definition: usb.h:218
#define USBD_STATUS_PORT_OPERATION_PENDING
Definition: usb.h:178
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
Definition: usb.h:95
#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL
Definition: usb.h:116
LONG USBD_STATUS
Definition: usb.h:172
@ UsbdPipeTypeControl
Definition: usb.h:257
#define URB_FUNCTION_OPEN_STATIC_STREAMS
Definition: usb.h:152
#define USBD_DEFAULT_PIPE_TRANSFER
Definition: usb.h:163
#define USBD_STATUS_INVALID_URB_FUNCTION
Definition: usb.h:202
#define USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR
Definition: usb.h:214
#define URB_FUNCTION_GET_STATUS_FROM_DEVICE
Definition: usb.h:105
#define USBD_PF_VALID_MASK
Definition: usb.h:285
PVOID USBD_CONFIGURATION_HANDLE
Definition: usb.h:242
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
Definition: usb.h:97
#define URB_FUNCTION_CLOSE_STATIC_STREAMS
Definition: usb.h:153
#define USBD_STATUS_BAD_START_FRAME
Definition: usb.h:209
#define USBD_STATUS_BUFFER_TOO_SMALL
Definition: usb.h:217
#define URB_FUNCTION_ISOCH_TRANSFER
Definition: usb.h:96
#define USBD_CLIENT_INTERFACE_VERSION
Definition: usbdclient.h:18
struct _USBD_CLIENT_INTERFACE * PUSBD_CLIENT_INTERFACE
_In_opt_ PVOID HubContext
Definition: usbdhub.h:41
struct _REGISTER_COMPOSITE_DEVICE * PREGISTER_COMPOSITE_DEVICE
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
Definition: usbdlib.h:333
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
#define IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO
Definition: usbioctl.h:68
#define IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DEVICE
Definition: usbioctl.h:760
#define IOCTL_INTERNAL_USB_RESET_PORT
Definition: usbioctl.h:35
#define IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION
Definition: usbioctl.h:766
#define IOCTL_INTERNAL_USB_CYCLE_PORT
Definition: usbioctl.h:53
#define IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
Definition: usbioctl.h:62
#define IOCTL_INTERNAL_USB_FAIL_GET_STATUS_FROM_DEVICE
Definition: usbioctl.h:769
enum _USB_CONNECTION_STATUS USB_CONNECTION_STATUS
struct _USB_HUB_NAME * PUSB_HUB_NAME
#define IOCTL_INTERNAL_USB_GET_HUB_COUNT
Definition: usbioctl.h:50
#define IOCTL_INTERNAL_USB_ENABLE_PORT
Definition: usbioctl.h:47
#define IOCTL_INTERNAL_USB_GET_BUS_INFO
Definition: usbioctl.h:59
@ DeviceFailedEnumeration
Definition: usbioctl.h:280
@ DeviceConnected
Definition: usbioctl.h:279
@ DeviceGeneralFailure
Definition: usbioctl.h:281
@ DeviceNotEnoughPower
Definition: usbioctl.h:283
#define IOCTL_INTERNAL_USB_UNREGISTER_COMPOSITE_DEVICE
Definition: usbioctl.h:763
#define IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
Definition: usbioctl.h:38
#define IOCTL_INTERNAL_USB_GET_HUB_NAME
Definition: usbioctl.h:56
#define IOCTL_INTERNAL_USB_GET_PORT_STATUS
Definition: usbioctl.h:44
WdfObjectDelete(String)
WdfStringGetUnicodeString(Original, &Name)
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ WDFCOLLECTION _In_ ULONG Index
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
FORCEINLINE VOID WDF_DEVICE_PNP_CAPABILITIES_INIT(_Out_ PWDF_DEVICE_PNP_CAPABILITIES Caps)
Definition: wdfdevice.h:1545
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
@ WdfPowerDevicePrepareForHibernation
Definition: wdfdevice.h:428
@ WdfPowerDeviceD3Final
Definition: wdfdevice.h:427
@ WdfPowerDeviceD0
Definition: wdfdevice.h:423
@ WdfPowerDeviceD3
Definition: wdfdevice.h:426
@ WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP
Definition: wdfdevice.h:437
enum _WDF_POWER_DEVICE_STATE WDF_POWER_DEVICE_STATE
_In_ WDFCMRESLIST _In_ WDFCMRESLIST ResourcesTranslated
Definition: wdfdevice.h:891
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_POWER_POLICY_IDLE_SETTINGS Settings
Definition: wdfdevice.h:2601
@ WdfDeviceFailedAttemptRestart
Definition: wdfdevice.h:469
@ WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO
Definition: wdfdevice.h:1645
@ WdfSpecialFileBoot
Definition: wdfdevice.h:445
@ WdfSpecialFileHibernation
Definition: wdfdevice.h:443
@ WdfSpecialFileDump
Definition: wdfdevice.h:444
@ WdfSpecialFilePaging
Definition: wdfdevice.h:442
#define WdfDeviceStopIdle(Device, WaitForD0)
Definition: wdfdevice.h:1977
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2231
FORCEINLINE VOID WDF_PNPPOWER_EVENT_CALLBACKS_INIT(_Out_ PWDF_PNPPOWER_EVENT_CALLBACKS Callbacks)
Definition: wdfdevice.h:1214
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_In_ WDF_POWER_DEVICE_STATE TargetState
Definition: wdfdevice.h:859
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1707
FORCEINLINE VOID WDF_DEVICE_POWER_CAPABILITIES_INIT(_Out_ PWDF_DEVICE_POWER_CAPABILITIES Caps)
Definition: wdfdevice.h:1612
_In_ WDFCMRESLIST ResourcesRaw
Definition: wdfdevice.h:888
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3040
#define WdfDeviceResumeIdle(Device)
Definition: wdfdevice.h:1983
FORCEINLINE VOID WDF_REMOVE_LOCK_OPTIONS_INIT(_Out_ PWDF_REMOVE_LOCK_OPTIONS RemoveLockOptions, _In_ ULONG Flags)
Definition: wdfdevice.h:1667
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ WDFDEVICE _In_ LPCGUID InterfaceType
Definition: wdffdo.h:463
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_In_ WDFINTERRUPT _In_ WDF_INTERRUPT_POLICY Policy
Definition: wdfinterrupt.h:653
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:443
@ WdfIoQueueDispatchSequential
Definition: wdfio.h:78
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params, _In_ PDEVICE_OBJECT DeviceObject)
Definition: wdfiotarget.h:287
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
#define WdfObjectDereferenceWithTag(Handle, Tag)
Definition: wdfobject.h:829
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
#define WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(_contexttype, _castingfunction)
Definition: wdfobject.h:350
#define WdfObjectReferenceWithTag(Handle, Tag)
Definition: wdfobject.h:806
FORCEINLINE VOID WDF_PDO_EVENT_CALLBACKS_INIT(_Out_ PWDF_PDO_EVENT_CALLBACKS Callbacks)
Definition: wdfpdo.h:199
_In_ WDFIORESREQLIST IoResourceRequirementsList
Definition: wdfpdo.h:78
WDF_EXTERN_C_START typedef _In_ LPGUID _Inout_ PINTERFACE ExposedInterface
WDF_EXTERN_C_START typedef _In_ LPGUID _Inout_ PINTERFACE _Inout_opt_ PVOID ExposedInterfaceSpecificData
FORCEINLINE VOID NTAPI WdfDeviceInterfaceReferenceNoOp(_In_ PVOID Context)
FORCEINLINE VOID NTAPI WdfDeviceInterfaceDereferenceNoOp(_In_ PVOID Context)
FORCEINLINE VOID WDF_QUERY_INTERFACE_CONFIG_INIT(_Out_ PWDF_QUERY_INTERFACE_CONFIG InterfaceConfig, _In_opt_ PINTERFACE Interface, _In_ CONST GUID *InterfaceType, _In_opt_ PFN_WDF_DEVICE_PROCESS_QUERY_INTERFACE_REQUEST EvtDeviceProcessQueryInterfaceRequest)
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ FORCEINLINE BOOLEAN WdfRequestSend(_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_opt_ PWDF_REQUEST_SEND_OPTIONS Options)
Definition: wdfrequest.h:677
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
@ WDF_REQUEST_REUSE_NO_FLAGS
Definition: wdfrequest.h:92
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
Definition: wdfrequest.h:364
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
@ WdfTrue
Definition: wdftypes.h:88
@ WdfFalse
Definition: wdftypes.h:87
#define WDF_NO_SEND_OPTIONS
Definition: wdftypes.h:109
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
_In_ NTSTATUS _In_ USBD_STATUS UsbdStatus
Definition: wdfusb.h:403
_In_ WDFUSBPIPE Pipe
Definition: wdfusb.h:1741
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
_IRQL_requires_same_ _In_opt_ PVOID Argument1
Definition: cmtypes.h:697
enum _D3COLD_LAST_TRANSITION_STATUS * PD3COLD_LAST_TRANSITION_STATUS
#define STATUS_CONTINUE_COMPLETION
#define IRP_MN_QUERY_PNP_DEVICE_STATE
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_QUERY_INTERFACE
#define IRP_MN_START_DEVICE
#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS
_Out_ PBOOLEAN D3ColdSupported
Definition: iotypes.h:7546
#define IRP_MN_QUERY_ID
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_QUERY_DEVICE_TEXT
#define IRP_MN_SET_POWER
_In_ SYSTEM_POWER_STATE _Out_ PDEVICE_WAKE_DEPTH DeepestWakeableDstate
Definition: iotypes.h:7536
#define PNP_LOCATION_INTERFACE_VERSION
Definition: iotypes.h:5536
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
@ LastDStateTransitionD3hot
Definition: iotypes.h:7553
@ LastDStateTransitionD3cold
Definition: iotypes.h:7554
@ DeviceWakeDepthD2
Definition: iotypes.h:7498
@ DeviceWakeDepthNotWakeable
Definition: iotypes.h:7495
#define IRP_MN_DEVICE_ENUMERATED
#define IRP_MJ_POWER
_In_ SYSTEM_POWER_STATE SystemPowerState
Definition: iotypes.h:7535
_Out_ PD3COLD_LAST_TRANSITION_STATUS LastTransitionStatus
Definition: iotypes.h:7563
@ BusQueryDeviceID
Definition: iotypes.h:2951
enum _DEVICE_WAKE_DEPTH * PDEVICE_WAKE_DEPTH
struct _D3COLD_SUPPORT_INTERFACE * PD3COLD_SUPPORT_INTERFACE
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:467
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
_In_ LPCGUID SettingGuid
Definition: pofuncs.h:120
#define NT_ASSERT
Definition: rtlfuncs.h:3334