ReactOS 0.4.17-dev-1281-g065abb3
hubtunnel.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: USB4 host routers behind hub ports: binding, port mappings and power coupling
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9
10#define NDEBUG
11#include <debug.h>
12
13/* {9C0D3EAE-FBA6-4E08-9E8D-181CBB3997D6}: virtual power PDO of a USB4 host router */
15 { 0x9c0d3eae, 0xfba6, 0x4e08, { 0x9e, 0x8d, 0x18, 0x1c, 0xbb, 0x39, 0x97, 0xd6 } };
16
17/* Root port to host router names, written on the hub's own PDO */
19 { { 0xb5a825b8, 0x3907, 0x40b5, { 0xab, 0xca, 0x84, 0x51, 0xe2, 0x45, 0x3d, 0x5f } }, 1 };
20
21/* PCI properties ucx01000 copies from the controller onto the root hub PDO */
23 { { 0x3ab22e31, 0x8264, 0x4b4e, { 0x9a, 0xf5, 0xa8, 0xd2, 0xd8, 0xe3, 0x3e, 0x62 } }, 40 };
25 { { 0x3ab22e31, 0x8264, 0x4b4e, { 0x9a, 0xf5, 0xa8, 0xd2, 0xd8, 0xe3, 0x3e, 0x62 } }, 42 };
26
27/* Reference string of the power PDO interface: prefix, then ^<acpi>^<dvsec>^<cmid> */
28#define HUB_USB4_REFERENCE_PREFIX L"Usb4-Host-Interface-"
29#define HUB_USB4_REFERENCE_PREFIX_CHARS 20
30#define HUB_USB4_REFERENCE_CHARS 256
31#define HUB_USB4_FIELD_SEPARATOR L'^'
32
33/* Symbolic link copy the open work item carries, and the name it opens */
34#define HUB_USB4_LINK_CHARS 256
35#define HUB_USB4_OPEN_NAME_CHARS 256
36
37/* DVSEC port attributes: a 3 bit host index per port nibble, 7 for none */
38#define HUB_USB4_HOST_INDEX_MASK 0x07
39#define HUB_USB4_NO_HOST 0x07
40#define HUB_USB4_DVSEC_NAME_CHARS 20
41
42/* Room per port mapping entry beyond the host name: port number, '#' and the NUL */
43#define HUB_USB4_MAPPING_EXTRA_BYTES 14
44
47{
48 Idle,
49 Opening,
50 Open,
51 Closing,
52 Closed
53};
54
57{
58 /* Escaped name of the first port bound to this host */
59 WDFSTRING Name;
60 WDFIOTARGET Target;
61 WDFWAITLOCK Lock;
63
64 /* Physical device of the opened target, NULL while closed */
68};
69
71{
73
74 /* Set once the target is open */
76};
77
79
81{
84};
85
87
88static DRIVER_NOTIFICATION_CALLBACK_ROUTINE HubUsb4InterfaceChange;
89static EVT_WDF_WORKITEM HubUsb4OpenWorkItem;
90static EVT_WDF_IO_TARGET_QUERY_REMOVE HubUsb4TargetQueryRemove;
91static EVT_WDF_IO_TARGET_REMOVE_CANCELED HubUsb4TargetRemoveCanceled;
92static EVT_WDF_IO_TARGET_REMOVE_COMPLETE HubUsb4TargetRemoveComplete;
93
94/* HOST RECORDS **************************************************************/
95
99HubUsb4Initialize(
100 _In_ HubFdo* Hub)
101{
104
105 PAGED_CODE();
106
108 Attributes.ParentObject = Hub->m_Device;
109
110 Status = WdfCollectionCreate(&Attributes, &Hub->m_Usb4Hosts);
111 if (!NT_SUCCESS(Status))
112 {
113 DPRINT1("Hub %p USB4 host list not created 0x%lx\n", Hub, Status);
114 return Status;
115 }
116
117 Status = WdfWaitLockCreate(&Attributes, &Hub->m_Usb4HostsLock);
118 if (!NT_SUCCESS(Status))
119 DPRINT1("Hub %p USB4 host list lock not created 0x%lx\n", Hub, Status);
120
121 return Status;
122}
123
124static
126NTAPI
128 _In_ HubFdo* Hub,
130{
131 WDFOBJECT Item = WdfCollectionGetItem(Hub->m_Usb4Hosts, Index);
132
133 if (Item == NULL)
134 return NULL;
135
136 return (HubUsb4Host*)WdfMemoryGetBuffer((WDFMEMORY)Item, NULL);
137}
138
139/* Case insensitive; the caller holds the host list lock */
140static
142NTAPI
144 _In_ HubFdo* Hub,
146{
147 UNICODE_STRING HostName;
149 ULONG Count = WdfCollectionGetCount(Hub->m_Usb4Hosts);
150 ULONG Index;
151
152 for (Index = 0; Index < Count; Index++)
153 {
155 if (Host == NULL)
156 break;
157
159 if (RtlEqualUnicodeString(&HostName, Name, TRUE))
160 return Host;
161 }
162
163 return NULL;
164}
165
167static
169NTAPI
170HubUsb4FindPortHost(
172{
173 HubFdo* Hub = Port->m_Hub;
175
177
179 return HubUsb4FindHost(Hub, &Name);
180}
181
182/* The host router names fields the same way, so both sides compare equal */
183static
184VOID
185NTAPI
187 _In_ WDFSTRING Name)
188{
190 ULONG Index;
191
193
194 for (Index = 0; Index < Text.Length / sizeof(WCHAR); Index++)
195 {
197 Text.Buffer[Index] = L'#';
198 }
199}
200
201/* The record starts with a target that is created but not opened */
203static
205NTAPI
206HubUsb4CreateHost(
207 _In_ HubFdo* Hub,
208 _In_ WDFSTRING Name)
209{
212 WDFMEMORY Memory;
214
216 Attributes.ParentObject = Hub->m_Device;
217
218 Status = WdfMemoryCreate(&Attributes, NonPagedPool, HUB_TAG_HUB, sizeof(*Host), &Memory, (PVOID*)&Host);
220 {
221 DPRINT1("Hub %p USB4 host record not created 0x%lx\n", Hub, Status);
222 return Status;
223 }
224
226
228 Attributes.ParentObject = Memory;
229
230 Status = WdfIoTargetCreate(Hub->m_Device, &Attributes, &Host->Target);
231 if (!NT_SUCCESS(Status))
232 {
233 DPRINT1("Hub %p USB4 host target not created 0x%lx\n", Hub, Status);
234 goto Failed;
235 }
236
238
240 Attributes.ParentObject = Memory;
241
242 Status = WdfWaitLockCreate(&Attributes, &Host->Lock);
243 if (!NT_SUCCESS(Status))
244 {
245 DPRINT1("Hub %p USB4 host lock not created 0x%lx\n", Hub, Status);
246 goto Failed;
247 }
248
249 Host->Name = Name;
250
251 {
253 Status = WdfCollectionAdd(Hub->m_Usb4Hosts, Memory);
254 }
255
256 if (!NT_SUCCESS(Status))
257 {
258 DPRINT1("Hub %p USB4 host record not listed 0x%lx\n", Hub, Status);
259 goto Failed;
260 }
261
263
266 return Status;
267}
268
275NTAPI
276HubUsb4BindPort(
277 _In_ HubFdo* Hub,
279 _In_ WDFSTRING Name)
280{
284
286
287 /* QUIRK: never cleared, even when no port is bound on a later start */
289 {
290 DPRINT("Hub %p has ports behind a USB4 host router\n", Hub);
292 }
293
296
297 {
300 }
301
302 if (Host == NULL)
303 {
304 Status = HubUsb4CreateHost(Hub, Name);
305 if (!NT_SUCCESS(Status))
306 return Status;
307 }
308
311
312 DPRINT("Port %u belongs to USB4 host %wZ\n", Port->Number(), &Text);
313 return STATUS_SUCCESS;
314}
315
316/* DVSEC MAPPING *************************************************************/
317
323VOID
324NTAPI
325HubUsb4MapDvsecHosts(
326 _In_ HubFdo* Hub)
327{
332 WDFMEMORY Memory;
333 WDFSTRING Name;
335 PUCHAR Nibbles;
336 size_t Bytes;
337 ULONG64 Serial = 0;
340 ULONG HostIndex;
341 HubPort* Port;
343
344 PAGED_CODE();
345
346 {
348 if (WdfCollectionGetCount(Hub->m_Usb4Hosts) != 0)
349 return;
350 }
351
353 Status = WdfDeviceQueryPropertyEx(Hub->m_Device, &Property, sizeof(Serial), &Serial, &Required, &Type);
354 if (!NT_SUCCESS(Status))
355 {
357 DPRINT1("Hub %p PCI serial number query failed 0x%lx\n", Hub, Status);
358 return;
359 }
360
362 Status = WdfDeviceAllocAndQueryPropertyEx(Hub->m_Device,
363 &Property,
364 PagedPool,
366 &Memory,
367 &Type);
368 if (!NT_SUCCESS(Status))
369 {
370 DPRINT1("Hub %p has a PCI serial number but no USB4 port attributes 0x%lx\n", Hub, Status);
371 return;
372 }
373
374 Nibbles = (PUCHAR)WdfMemoryGetBuffer(Memory, &Bytes);
375 if (Nibbles == NULL)
376 {
377 DPRINT1("Hub %p USB4 port attributes are empty\n", Hub);
379 return;
380 }
381
382 /* Port N is the low nibble of byte (N - 1) / 2 when N is odd, the high one when even */
383 for (PortNumber = 1; PortNumber <= 2 * Bytes; PortNumber++)
384 {
385 HostIndex = Nibbles[(PortNumber - 1) / 2];
386 if ((PortNumber & 1) == 0)
387 HostIndex >>= 4;
388 HostIndex &= HUB_USB4_HOST_INDEX_MASK;
389
390 if (HostIndex == HUB_USB4_NO_HOST)
391 continue;
392
394 if (Port == NULL)
395 {
396 DPRINT1("Hub %p USB4 port attributes name port %lu, which does not exist\n", Hub, PortNumber);
397 continue;
398 }
399
400 if (!Port->IsUsb30())
401 {
402 DPRINT1("Hub %p USB4 port attributes name port %lu, which is not a USB 3 port\n", Hub, PortNumber);
403 continue;
404 }
405
407 Status = RtlUnicodeStringPrintf(&Text, L"%I64x_%lu", Serial, HostIndex);
408 if (!NT_SUCCESS(Status))
409 {
410 DPRINT1("Port %lu USB4 host name not formatted 0x%lx\n", PortNumber, Status);
411 break;
412 }
413
414 /* Parented to the hub so a restart does not leak them */
416 Attributes.ParentObject = Hub->m_Device;
417
418 Status = WdfStringCreate(&Text, &Attributes, &Name);
419 if (!NT_SUCCESS(Status))
420 {
421 DPRINT1("Port %lu USB4 host name string not created 0x%lx\n", PortNumber, Status);
422 break;
423 }
424
425 Status = HubUsb4BindPort(Hub, Port, Name);
426 if (!NT_SUCCESS(Status))
427 {
428 DPRINT1("Port %lu not bound to its USB4 host 0x%lx\n", PortNumber, Status);
430 break;
431 }
432 }
433
435}
436
437/* PORT MAPPING PROPERTY *****************************************************/
438
446NTAPI
447HubUsb4AssignPortMappings(
448 _In_ HubFdo* Hub)
449{
452 HubPort* Port;
455 PWCHAR End;
456 size_t Remaining;
457 SIZE_T Total = 0;
458 SIZE_T Add;
459 ULONG Used;
461
462 PAGED_CODE();
463
465 {
466 Port = CONTAINING_RECORD(Entry, HubPort, m_HubLink);
467 if (Port->m_Usb4HostName == NULL)
468 continue;
469
471 Add = Name.Length + HUB_USB4_MAPPING_EXTRA_BYTES;
472 if (Total + Add < Total)
473 {
474 DPRINT1("Hub %p USB4 port mapping size overflows\n", Hub);
476 }
477
478 Total += Add;
479 }
480
481 if (Total == 0)
482 return STATUS_SUCCESS;
483
484 Total += sizeof(WCHAR);
485 if (Total > MAXULONG)
486 {
487 DPRINT1("Hub %p USB4 port mapping is too large\n", Hub);
489 }
490
492 if (Buffer == NULL)
493 {
494 DPRINT1("Hub %p no memory for the USB4 port mapping\n", Hub);
496 }
497
498 Cursor = Buffer;
499 Remaining = Total;
501
503 {
504 Port = CONTAINING_RECORD(Entry, HubPort, m_HubLink);
505 if (Port->m_Usb4HostName == NULL)
506 continue;
507
509 Status = RtlStringCbPrintfExW(Cursor, Remaining, &End, &Remaining, 0, L"%u#%wZ", Port->Number(), &Name);
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT1("Port %u USB4 port mapping for %wZ not formatted 0x%lx\n", Port->Number(), &Name, Status);
513 goto Done;
514 }
515
516 /* This entry's NUL and the list's final NUL must still fit */
517 if (Remaining < 2 * sizeof(WCHAR))
518 {
519 DPRINT1("Hub %p USB4 port mapping buffer overflowed\n", Hub);
521 goto Done;
522 }
523
524 Cursor = End + 1;
525 Remaining -= sizeof(WCHAR);
526 }
527
529 Used = (ULONG)((Cursor + 1 - Buffer) * sizeof(WCHAR));
530
531 Status = IoSetDevicePropertyData(Hub->m_WdmPdo,
534 0,
536 Used,
537 Buffer);
538 if (!NT_SUCCESS(Status))
539 DPRINT1("Hub %p USB4 port mapping property not written 0x%lx\n", Hub, Status);
540
541Done:
543 return Status;
544}
545
546/* POWER COUPLING ************************************************************/
547
548/* FIXME: PoFx component relations are not implemented, so these only log the coupling to the host router's power PDO */
549static
550VOID
551NTAPI
553 _In_ HubFdo* Hub,
555{
556 DPRINT("Hub %p would depend on USB4 host router PDO %p; PoFx component relations are not available\n",
557 Hub, Host->PowerPdo);
558}
559
560static
561VOID
562NTAPI
564 _In_ HubFdo* Hub)
565{
566 DPRINT("Hub %p power relations are not reported\n", Hub);
567}
568
569/* The caller holds the host's lock */
570static
571VOID
572NTAPI
574 _In_ HubFdo* Hub,
576{
577 if (!Host->RelationAdded)
578 return;
579
580 DPRINT("Hub %p drops its dependency on USB4 host router PDO %p\n", Hub, Host->PowerPdo);
582}
583
586NTAPI
589{
590 return Child->m_Port->HasFlag(PortFlag::Usb4Host) &&
591 (Child->m_TunnelState == HUB_TUNNEL_STATE_TUNNELED ||
592 Child->m_TunnelState == HUB_TUNNEL_STATE_UNKNOWN);
593}
594
596VOID
597NTAPI
598HubUsb4AcquireHostPower(
600{
601 HubFdo* Hub = Port->m_Hub;
603
604 PAGED_CODE();
605
607 return;
608
609 Host = HubUsb4FindPortHost(Port);
610 if (Host == NULL)
611 {
612 DPRINT1("Port %u has no USB4 host record\n", Port->Number());
613 return;
614 }
615
616 HubWaitLockGuard Guard(Host->Lock);
617
619 if (Host->PowerReferences == 1 && Host->PowerPdo != NULL)
621}
622
624VOID
625NTAPI
626HubUsb4ReleaseHostPower(
628{
629 HubFdo* Hub = Port->m_Hub;
631 BOOLEAN Invalidate = FALSE;
632
633 PAGED_CODE();
634
636 return;
637
638 Host = HubUsb4FindPortHost(Port);
639 if (Host == NULL)
640 return;
641
642 {
643 HubWaitLockGuard Guard(Host->Lock);
644
647 {
649 Invalidate = TRUE;
650 }
651 }
652
653 if (Invalidate)
655}
656
657/* A reference taken while the target was closed is applied once it opens */
659static
660VOID
661NTAPI
662HubUsb4UpdatePowerRelations(
663 _In_ HubFdo* Hub,
665{
666 {
667 HubWaitLockGuard Guard(Host->Lock);
668
669 if (Host->PowerReferences != 0 && !Host->RelationAdded)
671 }
672
674}
675
676/* REMOTE TARGET *************************************************************/
677
678/* Caller holds the host list lock. QUIRK: the power reference count is kept across a reopen. */
680static
681VOID
682NTAPI
683HubUsb4CloseHost(
685{
686 HubUsb4Host* Host = Context->Host;
688
689 if (Host == NULL)
690 return;
691
692 DPRINT("Hub %p closing USB4 host target %p\n", Context->Hub, Host->Target);
693
694 {
695 HubWaitLockGuard Guard(Host->Lock);
696
698 Host->PowerPdo = NULL;
699
701 {
703 Close = TRUE;
704 }
705 }
706
707 if (!Close)
708 return;
709
710 WdfIoTargetClose(Host->Target);
711
712 HubWaitLockGuard Guard(Host->Lock);
714}
715
716static
718NTAPI
720 _In_ WDFIOTARGET Target)
721{
722 DPRINT("USB4 host target %p query remove\n", Target);
723 WdfIoTargetCloseForQueryRemove(Target);
724 return STATUS_SUCCESS;
725}
726
727/* QUIRK: the target is not opened again; the next interface arrival does that */
728static
729VOID
730NTAPI
732 _In_ WDFIOTARGET Target)
733{
734 DPRINT("USB4 host target %p remove canceled\n", Target);
735}
736
737static
738VOID
739NTAPI
741 _In_ WDFIOTARGET Target)
742{
744 HubFdo* Hub = Context->Hub;
745
746 DPRINT("USB4 host target %p removed\n", Target);
747
748 {
750 HubUsb4CloseHost(Context);
751 }
752
754}
755
756/* The host router takes an open whose name ends in "USB-<anything>" as one from the USB hub */
757static
758VOID
759NTAPI
761 _In_ WDFWORKITEM WorkItem)
762{
763 HubUsb4OpenContext* Open = HubUsb4GetOpenContext(WorkItem);
764 HubFdo* Hub = HubFdo::FromDevice((WDFDEVICE)WdfWorkItemGetParentObject(WorkItem));
770
773 if (!NT_SUCCESS(Status))
774 {
775 DPRINT1("Hub %p USB4 host target name not formatted 0x%lx\n", Hub, Status);
776 goto Failed;
777 }
778
780 Params.ShareAccess = FILE_SHARE_READ;
781 Params.CreateOptions = FILE_NON_DIRECTORY_FILE;
782 Params.EvtIoTargetQueryRemove = HubUsb4TargetQueryRemove;
783 Params.EvtIoTargetRemoveCanceled = HubUsb4TargetRemoveCanceled;
784 Params.EvtIoTargetRemoveComplete = HubUsb4TargetRemoveComplete;
785
786 Status = WdfIoTargetOpen(Host->Target, &Params);
787 if (!NT_SUCCESS(Status))
788 {
789 DPRINT1("Hub %p USB4 host target %wZ not opened 0x%lx\n", Hub, &Name, Status);
790 goto Failed;
791 }
792
793 {
795 HubWaitLockGuard HostGuard(Host->Lock);
796
799
800 Host->PowerPdo = WdfIoTargetWdmGetTargetPhysicalDevice(Host->Target);
802 }
803
804 HubUsb4UpdatePowerRelations(Hub, Host);
805
806 DPRINT("Hub %p opened USB4 host target %wZ, PDO %p\n", Hub, &Name, Host->PowerPdo);
808 return;
809
810Failed:
811 {
812 HubWaitLockGuard Guard(Host->Lock);
814 }
815
817}
818
819/* Any failure puts the host back to idle so later arrivals are not ignored */
821static
822VOID
823NTAPI
824HubUsb4QueueOpen(
825 _In_ HubFdo* Hub,
828{
832 WDFWORKITEM WorkItem;
835
837 Config.AutomaticSerialization = TRUE;
838
840 Attributes.ParentObject = Hub->m_Device;
841
842 Status = WdfWorkItemCreate(&Config, &Attributes, &WorkItem);
843 if (!NT_SUCCESS(Status))
844 {
845 DPRINT1("Hub %p USB4 host open work item not created 0x%lx\n", Hub, Status);
846 goto Failed;
847 }
848
849 Open = HubUsb4GetOpenContext(WorkItem);
850 Open->Host = Host;
851
852 Chars = SymbolicLink->Length / sizeof(WCHAR);
853 if ((SymbolicLink->Length & 1) != 0 ||
854 SymbolicLink->Length > SymbolicLink->MaximumLength ||
855 (SymbolicLink->Buffer == NULL && SymbolicLink->Length != 0))
856 {
858 }
860 {
862 }
863 else
864 {
868 return;
869 }
870
871 DPRINT1("Hub %p USB4 host symbolic link %wZ not copied 0x%lx\n", Hub, SymbolicLink, Status);
873
875 HubWaitLockGuard Guard(Host->Lock);
877}
878
879/* INTERFACE WATCH ***********************************************************/
880
885static
887NTAPI
891{
893 HubFdo* Hub = HubFdo::FromDevice((WDFDEVICE)Context);
895 UNICODE_STRING AcpiName;
896 UNICODE_STRING DvsecName;
898 PWCHAR AcpiField;
899 PWCHAR DvsecField = NULL;
900 PWCHAR Mark;
905
906 PAGED_CODE();
907
908 if (!IsEqualGUID(Change->InterfaceClassGuid, HubUsb4PowerPdoInterface))
909 {
910 DPRINT("Hub %p ignores an interface change of another class\n", Hub);
911 return STATUS_SUCCESS;
912 }
913
915 {
916 DPRINT1("Hub %p cannot read USB4 power interface properties on this kernel\n", Hub);
917 return STATUS_SUCCESS;
918 }
919
920 Status = HubDriver.GetInterfaceProperty(Change->SymbolicLinkName,
921 &DEVPKEY_DeviceInterface_ReferenceString,
923 0,
924 sizeof(Reference),
925 Reference,
926 &Required,
927 &Type);
928 if (!NT_SUCCESS(Status))
929 {
930 DPRINT1("Hub %p USB4 power interface reference string query failed 0x%lx\n", Hub, Status);
931 return STATUS_SUCCESS;
932 }
933
935 {
936 DPRINT1("Hub %p USB4 power interface reference string has type 0x%lx\n", Hub, Type);
937 return STATUS_SUCCESS;
938 }
939
940 Reference[RTL_NUMBER_OF(Reference) - 1] = UNICODE_NULL;
941
943 {
944 DPRINT1("Hub %p USB4 power interface has an invalid reference string %ws\n", Hub, Reference);
945 return STATUS_SUCCESS;
946 }
947
949 if (Mark == NULL)
950 {
951 DPRINT1("Hub %p USB4 power interface reference string %ws has no fields\n", Hub, Reference);
952 return STATUS_SUCCESS;
953 }
954
955 AcpiField = Mark + 1;
957 if (Mark != NULL)
958 {
960 DvsecField = Mark + 1;
961
962 Mark = wcschr(DvsecField, HUB_USB4_FIELD_SEPARATOR);
963 if (Mark != NULL)
965 }
966
967 RtlInitUnicodeString(&AcpiName, AcpiField);
968
969 {
971
972 if (AcpiName.Length != 0)
973 Host = HubUsb4FindHost(Hub, &AcpiName);
974
975 if (Host == NULL && DvsecField != NULL)
976 {
977 RtlInitUnicodeString(&DvsecName, DvsecField);
978 Host = HubUsb4FindHost(Hub, &DvsecName);
979 }
980 }
981
982 if (Host == NULL)
983 {
984 DPRINT1("Hub %p has no USB4 host for %ws\n", Hub, Reference);
985 return STATUS_SUCCESS;
986 }
987
988 /* Removal is handled by the target's remove callbacks */
990 {
991 DPRINT("Hub %p USB4 host %p power interface removed\n", Hub, Host);
992 return STATUS_SUCCESS;
993 }
994
995 DPRINT("Hub %p USB4 host %p power interface arrived\n", Hub, Host);
996
997 {
998 HubWaitLockGuard Guard(Host->Lock);
999
1001 {
1003 Open = TRUE;
1004 }
1005 }
1006
1007 if (Open)
1008 HubUsb4QueueOpen(Hub, Host, Change->SymbolicLinkName);
1009
1010 return STATUS_SUCCESS;
1011}
1012
1013/* Registered from the hub's D0 entry since there is no PoFx callback */
1015VOID
1016NTAPI
1017HubUsb4RegisterNotification(
1018 _In_ HubFdo* Hub)
1019{
1021
1022 PAGED_CODE();
1023
1025 return;
1026
1030 WdfDriverWdmGetDriverObject(WdfGetDriver()),
1032 Hub->m_Device,
1034 if (!NT_SUCCESS(Status))
1035 {
1036 DPRINT1("Hub %p USB4 power interface notification not registered 0x%lx\n", Hub, Status);
1038 }
1039}
1040
1042VOID
1043NTAPI
1044HubUsb4UnregisterNotification(
1045 _In_ HubFdo* Hub)
1046{
1047 PAGED_CODE();
1048
1049 if (Hub->m_Usb4Notification == NULL)
1050 return;
1051
1054}
1055
1056/* Hub cleanup: every opened host target is closed */
1058VOID
1059NTAPI
1060HubUsb4CloseAllHosts(
1061 _In_ HubFdo* Hub)
1062{
1064 ULONG Count;
1065 ULONG Index;
1066
1067 PAGED_CODE();
1068
1070 {
1072
1073 Count = WdfCollectionGetCount(Hub->m_Usb4Hosts);
1074 for (Index = 0; Index < Count; Index++)
1075 {
1077 if (Host == NULL)
1078 break;
1079
1080 if (Host->Target != NULL)
1081 HubUsb4CloseHost(HubUsb4GetTargetContext(Host->Target));
1082 }
1083 }
1084
1086}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define DPRINT1
Definition: precomp.h:8
#define STATUS_INTEGER_OVERFLOW
Definition: log.c:20
HubFdo * Hub
Definition: bootdev.cpp:261
USHORT Change
Definition: bootdev.cpp:133
RtlInitEmptyUnicodeString(SymbolicLinkName, NULL, 0)
Definition: bufpool.h:45
Definition: fdo.h:132
WDFDEVICE m_Device
Definition: fdo.h:349
PDEVICE_OBJECT m_WdmPdo
Definition: fdo.h:350
BOOLEAN m_HasUsb4Ports
Definition: fdo.h:467
static HubFdo * FromDevice(_In_ WDFDEVICE Device)
Definition: fdo.cpp:37
WDFWAITLOCK m_Usb4HostsLock
Definition: fdo.h:474
HubMux m_Mux
Definition: fdo.h:407
WDFCOLLECTION m_Usb4Hosts
Definition: fdo.h:473
PVOID m_Usb4Notification
Definition: fdo.h:477
HubPort * FindPort(_In_ ULONG PortNumber)
Definition: fanout.cpp:42
WDFSTRING m_Usb4HostName
Definition: hubport.h:280
USHORT Number() const
Definition: hubport.h:213
BOOLEAN IsUsb30() const
Definition: hubport.h:219
VOID SetFlag(_In_ PortFlag Flag)
Definition: hubport.h:192
BOOLEAN HasFlag(_In_ PortFlag Flag) const
Definition: hubport.h:185
HubFdo * m_Hub
Definition: hubport.h:228
static VOID Mark(PGUI_CONSOLE_DATA GuiData)
Definition: conwnd.c:300
PUCHAR End
Definition: desccheck.cpp:2229
PUCHAR Cursor
Definition: desccheck.cpp:2228
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
#define DEVPROP_TYPE_STRING_LIST
Definition: devpropdef.h:48
#define DEVPROP_TYPE_STRING
Definition: devpropdef.h:47
KEVENT Done
Definition: devreq.cpp:1162
_In_ ULONG Attributes
Definition: dispmprt.h:1077
#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 wcschr
Definition: compat.h:17
#define FILE_SHARE_READ
Definition: compat.h:136
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:200
#define L(x)
Definition: resources.c:13
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
#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
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:24
#define HUB_TUNNEL_STATE_UNKNOWN
Definition: hubchild.h:54
#define HUB_TUNNEL_STATE_TUNNELED
Definition: hubchild.h:52
return RtlUnicodeStringPrintf(Name, L"uxd_port_%03u", PortNumber)
ULONG Chars
Definition: hubtunnel.cpp:833
static const DEVPROPKEY HubKeyPciSerialNumber
Definition: hubtunnel.cpp:22
_In_ HubPort * Port
Definition: hubtunnel.cpp:278
#define HUB_USB4_HOST_INDEX_MASK
Definition: hubtunnel.cpp:38
static const DEVPROPKEY HubKeyUsb4PortMappings
Definition: hubtunnel.cpp:18
WDFMEMORY Memory
Definition: hubtunnel.cpp:212
WdfStringGetUnicodeString(Name, &Text)
WDF_OBJECT_ATTRIBUTES_INIT & Attributes
Definition: hubtunnel.cpp:215
#define HUB_USB4_MAPPING_EXTRA_BYTES
Definition: hubtunnel.cpp:43
static VOID NTAPI HubUsb4EscapeName(_In_ WDFSTRING Name)
Definition: hubtunnel.cpp:186
static HubUsb4Host *NTAPI HubUsb4HostAt(_In_ HubFdo *Hub, _In_ ULONG Index)
Definition: hubtunnel.cpp:127
BOOLEAN NTAPI HubUsb4NeedsHostPower(_In_ HubChild *Child)
Definition: hubtunnel.cpp:587
HubUsb4TargetState
Definition: hubtunnel.cpp:47
static HubUsb4Host *NTAPI HubUsb4FindHost(_In_ HubFdo *Hub, _In_ PCUNICODE_STRING Name)
Definition: hubtunnel.cpp:143
#define HUB_USB4_DVSEC_NAME_CHARS
Definition: hubtunnel.cpp:40
WdfObjectDelete(WorkItem)
static const DEVPROPKEY HubKeyPciUsb4PortAttributes
Definition: hubtunnel.cpp:24
NTSTATUS Status
Definition: hubtunnel.cpp:213
WdfWorkItemEnqueue(WorkItem)
PAGED_CODE()
static EVT_WDF_IO_TARGET_REMOVE_COMPLETE HubUsb4TargetRemoveComplete
Definition: hubtunnel.cpp:92
return STATUS_SUCCESS
Definition: hubtunnel.cpp:262
static EVT_WDF_IO_TARGET_QUERY_REMOVE HubUsb4TargetQueryRemove
Definition: hubtunnel.cpp:90
static VOID NTAPI HubUsb4RemovePowerRelation(_In_ HubFdo *Hub, _In_ HubUsb4Host *Host)
Definition: hubtunnel.cpp:573
WDFWORKITEM WorkItem
Definition: hubtunnel.cpp:832
static VOID NTAPI HubUsb4InvalidatePowerRelations(_In_ HubFdo *Hub)
Definition: hubtunnel.cpp:563
static EVT_WDF_IO_TARGET_REMOVE_CANCELED HubUsb4TargetRemoveCanceled
Definition: hubtunnel.cpp:91
#define HUB_USB4_REFERENCE_CHARS
Definition: hubtunnel.cpp:30
static EVT_WDF_WORKITEM HubUsb4OpenWorkItem
Definition: hubtunnel.cpp:89
WDF_WORKITEM_CONFIG_INIT & Config
Definition: hubtunnel.cpp:836
#define HUB_USB4_NO_HOST
Definition: hubtunnel.cpp:39
#define HUB_USB4_REFERENCE_PREFIX
Definition: hubtunnel.cpp:28
#define HUB_USB4_OPEN_NAME_CHARS
Definition: hubtunnel.cpp:35
HubUsb4GetTargetContext(Host->Target) -> Hub=Hub
HubUsb4OpenContext * Open
Definition: hubtunnel.cpp:831
#define HUB_USB4_LINK_CHARS
Definition: hubtunnel.cpp:34
_In_ HubUsb4Host _In_ PCUNICODE_STRING SymbolicLink
Definition: hubtunnel.cpp:828
#define HUB_USB4_REFERENCE_PREFIX_CHARS
Definition: hubtunnel.cpp:29
static const GUID HubUsb4PowerPdoInterface
Definition: hubtunnel.cpp:14
HubUsb4Host * Host
Definition: hubtunnel.cpp:211
_In_ WDFSTRING Name
Definition: hubtunnel.cpp:209
static DRIVER_NOTIFICATION_CALLBACK_ROUTINE HubUsb4InterfaceChange
Definition: hubtunnel.cpp:88
static VOID NTAPI HubUsb4AddPowerRelation(_In_ HubFdo *Hub, _In_ HubUsb4Host *Host)
Definition: hubtunnel.cpp:552
#define HUB_USB4_FIELD_SEPARATOR
Definition: hubtunnel.cpp:31
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
Definition: hubucx.h:227
_In_ ULONG PortNumber
Definition: hubucx.h:272
#define HUB_TAG_HUB
Definition: hubutil.h:12
ULONG Total
Definition: hubwmi.cpp:548
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
_In_ UINT Bytes
Definition: mmcopy.h:9
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
#define _Inout_opt_
Definition: no_sal2.h:216
#define _In_
Definition: no_sal2.h:158
#define FILE_READ_DATA
Definition: nt_native.h:628
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define LOCALE_NEUTRAL
#define UNICODE_NULL
NTSTRSAFEVAPI RtlStringCbPrintfExW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd, _Out_opt_ size_t *pcbRemaining, _In_ STRSAFE_DWORD dwFlags, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1335
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI IoRegisterPlugPlayNotification(_In_ IO_NOTIFICATION_EVENT_CATEGORY EventCategory, _In_ ULONG EventCategoryFlags, _In_opt_ PVOID EventCategoryData, _In_ PDRIVER_OBJECT DriverObject, _In_ PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, _Inout_opt_ PVOID Context, _Out_ PVOID *NotificationEntry)
Definition: pnpnotify.c:346
NTSTATUS NTAPI IoUnregisterPlugPlayNotification(_In_ PVOID NotificationEntry)
Definition: pnpnotify.c:480
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
ULONG64 Serial
Definition: rhubpdo.cpp:335
ULONG Required
Definition: rhubpdo.cpp:336
@ Close
Definition: sacdrv.h:268
@ Failed
Definition: arc.h:88
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:73
PFN_HUB_GET_INTERFACE_PROPERTY GetInterfaceProperty
Definition: hubdriver.h:116
LIST_ENTRY Ports
Definition: fdo.h:69
BOOLEAN RelationAdded
Definition: hubtunnel.cpp:67
LONG PowerReferences
Definition: hubtunnel.cpp:66
WDFWAITLOCK Lock
Definition: hubtunnel.cpp:61
WDFIOTARGET Target
Definition: hubtunnel.cpp:60
HubUsb4TargetState State
Definition: hubtunnel.cpp:62
WDFSTRING Name
Definition: hubtunnel.cpp:59
PDEVICE_OBJECT PowerPdo
Definition: hubtunnel.cpp:65
WCHAR SymbolicLink[HUB_USB4_LINK_CHARS]
Definition: hubtunnel.cpp:82
HubUsb4Host * Host
Definition: hubtunnel.cpp:83
HubUsb4Host * Host
Definition: hubtunnel.cpp:75
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define MAXULONG
Definition: typedefs.h:251
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
USHORT Count
Definition: userreq.cpp:200
UNICODE_STRING Text
Definition: userreq.cpp:261
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFCOLLECTION _In_ WDFOBJECT Item
FORCEINLINE VOID WDF_DEVICE_PROPERTY_DATA_INIT(_Out_ PWDF_DEVICE_PROPERTY_DATA PropertyData, _In_ const DEVPROPKEY *PropertyKey)
Definition: wdfdevice.h:1941
FORCEINLINE WDFDRIVER WdfGetDriver(VOID)
Definition: wdfdriver.h:194
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params, _In_ PCUNICODE_STRING TargetDeviceName, _In_ ACCESS_MASK DesiredAccess)
Definition: wdfiotarget.h:323
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG _In_ _Out_ WDFMEMORY * Memory
Definition: wdfmemory.h:169
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
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
_In_ PVOID NotificationStructure
Definition: iofuncs.h:1225
struct _DEVICE_INTERFACE_CHANGE_NOTIFICATION * PDEVICE_INTERFACE_CHANGE_NOTIFICATION
@ EventCategoryDeviceInterfaceChange
Definition: iotypes.h:1226
#define PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES
Definition: iotypes.h:1239