ReactOS 0.4.17-dev-1281-g065abb3
devconfig.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: Configuration and interface records behind client select requests
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "usbhub3.h"
9#include "desccheck.h"
10#include "devhcd.h"
11
12#define NDEBUG
13#include <debug.h>
14
15/* Every endpoint reports at most this interval to the client, whatever its type */
16#define CLIENT_INTERVAL_CAP 6
17
18/* Devices below USB 2.5 pack extra transactions into wMaxPacketSize bits 12:11 */
19#define BCD_USB_25 0x0250
20
21/* Isochronous companions on SuperSpeedPlus have an extra descriptor */
22#define COMPANION_LENGTH 6
23#define SSP_COMPANION_LENGTH 8
24
26static
27PURB
31{
33
35 WdfRequestGetParameters(Child->m_ClientRequest, &Params);
36 return (PURB)Params.Parameters.Others.Arg1;
37}
38
39/* The registry filter is a ULONG count followed by (interface, alternate) byte pairs */
40static
47{
48 PULONG Filter = (PULONG)Child->m_AlternateSettingFilter;
49 PUCHAR Pairs;
51
52 if (Filter == NULL)
53 return FALSE;
54
55 Pairs = (PUCHAR)(Filter + 1);
56 for (Index = 0; Index < *Filter; Index++)
57 {
58 if (Pairs[Index * 2] == InterfaceNumber && Pairs[Index * 2 + 1] == AlternateSetting)
59 return TRUE;
60 }
61
62 return FALSE;
63}
64
65/* UCX endpoint arrays */
66
67static
68VOID
72{
73 UCXENDPOINT** Arrays[] = { &Child->m_EndpointsToEnable,
74 &Child->m_EndpointsUnchanged,
75 &Child->m_EndpointsToDisable };
77
78 Child->m_EndpointArrayCapacity = 0;
79
80 for (Index = 0; Index < RTL_NUMBER_OF(Arrays); Index++)
81 {
82 if (*Arrays[Index] != NULL)
83 {
85 *Arrays[Index] = NULL;
86 }
87 }
88}
89
90/* All three arrays share one capacity and only grow; the old ones are freed after every new allocation succeeds */
91static
97{
98 UCXENDPOINT* Fresh[3];
100
101 Child->m_EnableCount = 0;
102 Child->m_DisableCount = 0;
103 Child->m_UnchangedCount = 0;
104
105 if (Count <= Child->m_EndpointArrayCapacity)
106 return STATUS_SUCCESS;
107
108 for (Index = 0; Index < RTL_NUMBER_OF(Fresh); Index++)
109 {
110 Fresh[Index] = (UCXENDPOINT*)ExAllocatePoolZero(NonPagedPool,
111 Count * sizeof(UCXENDPOINT),
113 if (Fresh[Index] == NULL)
114 {
115 DPRINT1("Device %p no memory for %lu endpoint handles\n", Child, Count);
116 while (Index-- != 0)
119 }
120 }
121
123 Child->m_EndpointsToEnable = Fresh[0];
124 Child->m_EndpointsUnchanged = Fresh[1];
125 Child->m_EndpointsToDisable = Fresh[2];
126 Child->m_EndpointArrayCapacity = Count;
127 return STATUS_SUCCESS;
128}
129
130VOID
131NTAPI
135{
136 HubPipe* Pipe;
137 ULONG Index;
138
139 for (Index = 0; Index < Interface->PipeCount; Index++)
140 {
141 Pipe = &Interface->Pipes[Index];
142
143 switch (Pipe->State)
144 {
147 Child->m_EndpointsToDisable[Child->m_DisableCount++] = Pipe->Endpoint;
148 break;
149
151 Child->m_EndpointsUnchanged[Child->m_UnchangedCount++] = Pipe->Endpoint;
152 break;
153
155 break;
156
157 default:
158 DPRINT1("Device %p pipe %lu in unexpected state %u\n", Child, Index, (UCHAR)Pipe->State);
159 ASSERT(FALSE);
160 break;
161 }
162 }
163}
164
165/* Records */
166
167static
169NTAPI
173{
175 WDFMEMORY Memory;
176 ULONG Size;
178
180 Size = max(Size, (ULONG)sizeof(*Config));
181
182 Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES,
185 Size,
186 &Memory,
187 (PVOID*)&Config);
188 if (!NT_SUCCESS(Status))
189 {
190 DPRINT1("Configuration record of %lu bytes not allocated 0x%lx\n", Size, Status);
191 *Result = NULL;
192 return Status;
193 }
194
196 Config->Memory = Memory;
197 InitializeListHead(&Config->Interfaces);
198 RtlCopyMemory(&Config->Descriptor, Source, Source->wTotalLength);
199
200 *Result = Config;
201 return STATUS_SUCCESS;
202}
203
204static
206NTAPI
209 _In_ BOOLEAN HasAlternates,
211{
213 WDFMEMORY Memory;
214 ULONG Size;
216
217 Size = FIELD_OFFSET(HubInterface, Pipes) + Descriptor->bNumEndpoints * sizeof(HubPipe);
218 Size = max(Size, (ULONG)sizeof(*Interface));
219
220 Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES,
223 Size,
224 &Memory,
225 (PVOID*)&Interface);
226 if (!NT_SUCCESS(Status))
227 {
228 DPRINT1("Interface %u record not allocated 0x%lx\n", Descriptor->bInterfaceNumber, Status);
229 *Result = NULL;
230 return Status;
231 }
232
234 Interface->Memory = Memory;
235 Interface->Descriptor = Descriptor;
236 Interface->PipeCount = Descriptor->bNumEndpoints;
237 Interface->HasAlternateSettings = HasAlternates;
238 Interface->NeedsSetInterface = HasAlternates;
239
240 *Result = Interface;
241 return STATUS_SUCCESS;
242}
243
244/* A half built configuration owns no UCX endpoints, so only memory goes */
245static
246VOID
247NTAPI
251{
253
254 while (!IsListEmpty(&Config->Interfaces))
255 {
256 Entry = RemoveHeadList(&Config->Interfaces);
257 HubChildDeleteInterface(Child, CONTAINING_RECORD(Entry, HubInterface, Link));
258 }
259
260 WdfObjectDelete(Config->Memory);
261}
262
263/* Pipes */
264
265/* TRUE when the descriptor type byte at Walk lies inside the buffer */
268NTAPI
272{
273 return Walk + 1 < End;
274}
275
276/* Records the optional companions after an endpoint; a bad one is just skipped */
277static
278VOID
279NTAPI
285{
288
289 if (!HubTypeFits(Walk, End))
290 return;
291
294 Companion->bLength == 0 ||
296 {
297 return;
298 }
299
300 Pipe->Companion = Companion;
301
302 if ((Pipe->Descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) != USB_ENDPOINT_TYPE_ISOCHRONOUS)
303 return;
304
305 if (!Pipe->ZeroBandwidth)
306 Client->MaximumPacketSize = Companion->wBytesPerInterval;
307
308 if (!Companion->bmAttributes.Isochronous.SspCompanion)
309 return;
310
311 Walk += Companion->bLength;
312 if (!HubTypeFits(Walk, End))
313 return;
314
317 SspCompanion->bLength != 0 &&
319 {
320 Pipe->IsochCompanion = SspCompanion;
321 }
322}
323
324/* Companion descriptors are not consumed here; the next pipe's skip loop steps over them */
325static
327NTAPI
334{
337 HubPipe* Pipe;
339 ULONG Index;
340
341 for (Index = 0; Index < Info->NumberOfPipes; Index++)
342 {
343 Client = &Info->Pipes[Index];
344 Pipe = &Interface->Pipes[Index];
345
346 if (Walk >= End)
347 {
348 DPRINT1("Device %p interface %u has fewer than %lu endpoint descriptors\n",
349 Child, Info->InterfaceNumber, Info->NumberOfPipes);
350 return STATUS_UNSUCCESSFUL;
351 }
352
353 Pipe->PipeFlags = Client->PipeFlags;
355
356 if (!HubTypeFits(Walk, End))
357 {
358 DPRINT1("Device %p interface %u descriptor runs past the configuration\n", Child, Info->InterfaceNumber);
359 return STATUS_UNSUCCESSFUL;
360 }
361
362 while (((PUSB_COMMON_DESCRIPTOR)Walk)->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
363 {
364 if (Walk[0] == 0)
365 {
366 DPRINT1("Device %p interface %u has a zero length descriptor\n", Child, Info->InterfaceNumber);
367 return STATUS_UNSUCCESSFUL;
368 }
369
370 Walk += Walk[0];
371 if (!HubTypeFits(Walk, End))
372 {
373 DPRINT1("Device %p interface %u has fewer than %lu endpoint descriptors\n",
374 Child, Info->InterfaceNumber, Info->NumberOfPipes);
375 return STATUS_UNSUCCESSFUL;
376 }
377 }
378
379 if (Walk + sizeof(USB_ENDPOINT_DESCRIPTOR) > End)
380 {
381 DPRINT1("Device %p interface %u endpoint descriptor runs past the configuration\n",
382 Child, Info->InterfaceNumber);
383 return STATUS_UNSUCCESSFUL;
384 }
385
387
388 /* The cached copy is what UCX sees, so the override goes there */
389 if (Pipe->PipeFlags & USBD_PF_CHANGE_MAX_PACKET)
390 Endpoint->wMaxPacketSize = Client->MaximumPacketSize;
391
392 Pipe->Descriptor = Endpoint;
393 Pipe->BytesToEnd = (ULONG)(End - Walk);
394
395 Packet = Endpoint->wMaxPacketSize;
396 if (Child->m_DeviceDescriptor.bcdUSB < BCD_USB_25)
397 Packet = (USHORT)((Packet & 0x7FF) * (((Packet >> 11) & 3) + 1));
398
399 Client->MaximumPacketSize = Packet;
400 Client->Interval = min(Endpoint->bInterval, CLIENT_INTERVAL_CAP);
401 Client->EndpointAddress = Endpoint->bEndpointAddress;
402 Client->PipeType = (USBD_PIPE_TYPE)(Endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK);
403
404 if (Client->MaximumPacketSize == 0)
405 Pipe->ZeroBandwidth = TRUE;
406
407 if (Endpoint->bLength == 0)
408 {
409 DPRINT1("Device %p endpoint 0x%x has a zero length\n", Child, Endpoint->bEndpointAddress);
410 return STATUS_UNSUCCESSFUL;
411 }
412
413 Walk += Endpoint->bLength;
415 }
416
417 return STATUS_SUCCESS;
418}
419
420/* Sanity checks */
421
422static
424NTAPI
427{
428 ULONG Index;
429
430 for (Index = 0; Index < Interface->PipeCount; Index++)
431 {
432 if ((Interface->Pipes[Index].Descriptor->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK) == 0)
433 return TRUE;
434 }
435
436 return FALSE;
437}
438
439static
441NTAPI
444{
446
447 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
448 {
450 return TRUE;
451 }
452
453 return FALSE;
454}
455
456/*
457 * One bit per endpoint number for control, IN and OUT. A control endpoint
458 * only conflicts with the control map, so the check depends on order.
459 */
460static
462NTAPI
465{
466 USHORT Seen[3] = { 0, 0, 0 };
470 USHORT Bit;
471 ULONG Map;
472 ULONG Index;
473
474 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
475 {
477
478 for (Index = 0; Index < Interface->PipeCount; Index++)
479 {
480 if (Interface->Pipes[Index].ZeroBandwidth)
481 continue;
482
483 Endpoint = Interface->Pipes[Index].Descriptor;
484 Bit = (USHORT)(1 << (Endpoint->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK));
485
487 Map = 0;
488 else if (USB_ENDPOINT_DIRECTION_IN(Endpoint->bEndpointAddress))
489 Map = 1;
490 else
491 Map = 2;
492
493 if ((Seen[0] | Seen[Map]) & Bit)
494 {
495 DPRINT1("Configuration %p uses endpoint 0x%x twice\n", Config, Endpoint->bEndpointAddress);
496 return STATUS_UNSUCCESSFUL;
497 }
498
499 Seen[Map] |= Bit;
500 }
501 }
502
503 return STATUS_SUCCESS;
504}
505
506static
508NTAPI
512{
515 ULONG I, J;
516
517 for (I = 0; I < First->PipeCount; I++)
518 {
519 A = First->Pipes[I].Descriptor;
520
521 for (J = 0; J < Second->PipeCount; J++)
522 {
523 B = Second->Pipes[J].Descriptor;
524
525 if (A->bEndpointAddress == B->bEndpointAddress &&
526 A->wMaxPacketSize != 0 &&
527 B->wMaxPacketSize != 0)
528 {
529 DPRINT1("Endpoint 0x%x shared by interface %u alternate %u and interface %u alternate %u\n",
530 A->bEndpointAddress,
531 First->Descriptor->bInterfaceNumber, First->Descriptor->bAlternateSetting,
532 Second->Descriptor->bInterfaceNumber, Second->Descriptor->bAlternateSetting);
534 }
535 }
536 }
537
538 return STATUS_SUCCESS;
539}
540
541static
542VOID
543NTAPI
547{
548 Child->m_LastNtStatus = Status;
549 if (Child->m_LastUsbdStatus == 0)
550 Child->m_LastUsbdStatus = HubNtStatusToUsbd(Status);
551}
552
553/* SELECT_CONFIGURATION */
554
555/* On failure the old configuration is restored; interface handles already written to the URB stay stale */
558{
561 struct _URB_SELECT_CONFIGURATION* Select = &Urb->UrbSelectConfiguration;
568 PUCHAR UrbEnd;
569 PUCHAR ConfigEnd;
570 BOOLEAN HasAlternates;
571 ULONG Total = 0;
573 KIRQL Irql;
574
575 Child->m_EnableCount = 0;
576
577 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
578 Child->ClearState(ChildState::ConfigurationValid);
579 Child->m_OldConfig = Child->m_CurrentConfig;
580 Child->m_CurrentConfig = NULL;
581 Child->ClearState(ChildState::AltSettingFiltered);
582 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
583
585 if (!NT_SUCCESS(Status))
586 goto Failed;
587
588 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
589 Child->m_CurrentConfig = Config;
590 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
591
592 ConfigEnd = (PUCHAR)&Config->Descriptor + Config->Descriptor.wTotalLength;
593 UrbEnd = (PUCHAR)Urb + Urb->UrbHeader.Length;
594
595 for (Info = &Select->Interface; (PUCHAR)Info + sizeof(USHORT) < UrbEnd; Info = Next)
596 {
598 &Config->Descriptor,
599 Info->InterfaceNumber,
600 Info->AlternateSetting,
601 -1,
602 -1,
603 -1,
604 &HasAlternates);
605 if (Descriptor == NULL || Info->Length == 0)
606 {
607 DPRINT1("Device %p SELECT_CONFIGURATION names missing interface %u alternate %u\n",
608 Child, Info->InterfaceNumber, Info->AlternateSetting);
611 goto Failed;
612 }
613
614 if (HubChildSettingFiltered(Child, Info->InterfaceNumber, Info->AlternateSetting))
615 {
616 DPRINT("Device %p interface %u alternate %u is filtered\n",
617 Child, Info->InterfaceNumber, Info->AlternateSetting);
618 Child->SetState(ChildState::AltSettingFiltered);
619 }
620
621 Info->NumberOfPipes = Descriptor->bNumEndpoints;
622 Total += Descriptor->bNumEndpoints;
624
626 if (!NT_SUCCESS(Status))
627 goto Failed;
628
629 Info->InterfaceHandle = Interface;
630
631 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
632 InsertTailList(&Config->Interfaces, &Interface->Link);
633 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
634
635 Info->Class = Descriptor->bInterfaceClass;
636 Info->SubClass = Descriptor->bInterfaceSubClass;
637 Info->Protocol = Descriptor->bInterfaceProtocol;
638
640 if (!NT_SUCCESS(Status))
641 {
643 goto Failed;
644 }
645 }
646
647 /* There is never a descriptor for endpoint zero */
649 {
650 DPRINT1("Device %p configuration has an endpoint zero descriptor\n", Child);
651 Child->m_LastUsbdStatus = USBD_STATUS_BAD_ENDPOINT_ADDRESS;
653 goto Failed;
654 }
655
657 if (!NT_SUCCESS(Status))
658 {
660 goto Failed;
661 }
662
663 Config->EndpointCount = Total;
664
665 /* The old configuration's pipes are collected into the same arrays, so size for the larger count */
667 (Child->m_OldConfig != NULL) ? max(Total, Child->m_OldConfig->EndpointCount) : Total);
668 if (!NT_SUCCESS(Status))
669 goto Failed;
670
671 if (Child->m_OldConfig != NULL)
672 {
673 Child->m_UnchangedCount = 0;
674 Child->m_DisableCount = 0;
675
676 for (Entry = Child->m_OldConfig->Interfaces.Flink;
677 Entry != &Child->m_OldConfig->Interfaces;
678 Entry = Entry->Flink)
679 {
681 }
682 }
683
684 Select->ConfigurationHandle = Config;
685 return TRUE;
686
687Failed:
689
690 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
691 Child->m_CurrentConfig = Child->m_OldConfig;
692 Child->m_OldConfig = NULL;
693 Child->SetState(ChildState::ConfigurationValid);
694 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
695
696 if (Config != NULL)
698
699 Select->ConfigurationHandle = NULL;
700 return FALSE;
701}
702
703/* SELECT_INTERFACE */
704
707{
710 PUSBD_INTERFACE_INFORMATION Info = &Urb->UrbSelectInterface.Interface;
711 HubConfiguration* Config = Child->m_CurrentConfig;
714 HubInterface* Old = NULL;
717 BOOLEAN HasAlternates = FALSE;
718 ULONG Total;
719 ULONG Index;
721 KIRQL Irql;
722
723 Child->m_NewInterface = NULL;
724 Child->m_EnableCount = 0;
725 Child->ClearState(ChildState::AltSettingFiltered);
726
727 /* The PDO completion path sets it again whatever happens here */
728 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
729 Child->ClearState(ChildState::ConfigurationValid);
730 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
731
732 if (Config != NULL)
733 {
735 &Config->Descriptor,
736 Info->InterfaceNumber,
737 Info->AlternateSetting,
738 -1,
739 -1,
740 -1,
741 &HasAlternates);
742 }
743
744 if (Descriptor == NULL)
745 {
746 DPRINT1("Device %p SELECT_INTERFACE names missing interface %u alternate %u\n",
747 Child, Info->InterfaceNumber, Info->AlternateSetting);
748 Child->m_LastUsbdStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
750 goto Failed;
751 }
752
753 if (HubChildSettingFiltered(Child, Info->InterfaceNumber, Info->AlternateSetting))
754 {
755 DPRINT("Device %p interface %u alternate %u is filtered\n",
756 Child, Info->InterfaceNumber, Info->AlternateSetting);
757 Child->SetState(ChildState::AltSettingFiltered);
758 }
759
761 Descriptor->bNumEndpoints * sizeof(USBD_PIPE_INFORMATION));
762 Info->Class = 0;
763 Info->SubClass = 0;
764 Info->Protocol = 0;
765 Info->Reserved = 0;
766 Info->InterfaceHandle = NULL;
767 Info->NumberOfPipes = Descriptor->bNumEndpoints;
768
770 if (!NT_SUCCESS(Status))
771 goto Failed;
772
773 Child->m_NextInterface = HasAlternates ? Interface : NULL;
774
775 Info->Class = Descriptor->bInterfaceClass;
776 Info->SubClass = Descriptor->bInterfaceSubClass;
777 Info->Protocol = Descriptor->bInterfaceProtocol;
778
780 Info,
781 Interface,
782 (PUCHAR)Descriptor + Descriptor->bLength,
783 (PUCHAR)&Config->Descriptor + Config->Descriptor.wTotalLength);
784 if (!NT_SUCCESS(Status))
785 {
786 Child->m_LastUsbdStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
787 goto Failed;
788 }
789
791 {
792 DPRINT1("Device %p interface %u has an endpoint zero descriptor\n", Child, Info->InterfaceNumber);
793 Child->m_LastUsbdStatus = USBD_STATUS_BAD_ENDPOINT_ADDRESS;
795 goto Failed;
796 }
797
798 /* The interface being replaced is only marked old once nothing can fail anymore */
799 Child->m_OldInterface = NULL;
800
801 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
802 {
804
805 if (Other->Descriptor->bInterfaceNumber == Info->InterfaceNumber)
806 {
807 Old = Other;
808 continue;
809 }
810
812 if (!NT_SUCCESS(Status))
813 goto Failed;
814 }
815
816 Total = Config->EndpointCount + Interface->PipeCount;
817
819 if (!NT_SUCCESS(Status))
820 goto Failed;
821
822 if (Old != NULL)
823 Total -= Old->PipeCount;
824
825 Child->m_UnchangedCount = 0;
826 Child->m_DisableCount = 0;
827
828 if (Old != NULL)
829 {
830 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
831 RemoveEntryList(&Old->Link);
832 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
833
834 Child->m_OldInterface = Old;
836 }
837
838 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
839 {
841
842 for (Index = 0; Index < Other->PipeCount; Index++)
843 Child->m_EndpointsUnchanged[Child->m_UnchangedCount++] = Other->Pipes[Index].Endpoint;
844 }
845
846 KeAcquireSpinLock(&Child->m_ConfigLock, &Irql);
847 InsertTailList(&Config->Interfaces, &Interface->Link);
848 Config->EndpointCount = Total;
849 KeReleaseSpinLock(&Child->m_ConfigLock, Irql);
850
851 Child->m_NewInterface = Interface;
852 Info->InterfaceHandle = Interface;
853 return TRUE;
854
855Failed:
857
858 if (Interface != NULL)
859 {
860 if (Child->m_NextInterface == Interface)
861 Child->m_NextInterface = NULL;
862
863 WdfObjectDelete(Interface->Memory);
864 }
865
866 Info->InterfaceHandle = (USBD_INTERFACE_HANDLE)(LONG_PTR)-1;
867 return FALSE;
868}
869
870/* Reset: the controller forgot every endpoint, so all of them are enabled again */
873{
875 HubConfiguration* Config = Child->m_CurrentConfig;
877 HubPipe* Pipe;
879 ULONG Index;
880
881 Child->m_EnableCount = 0;
882 Child->m_DisableCount = 0;
883 Child->m_UnchangedCount = 0;
884
885 if (Config == NULL)
886 return TRUE;
887
888 /* A failed earlier resize can leave the arrays short */
889 if (!NT_SUCCESS(HubChildSizeEndpointArrays(Child, Config->EndpointCount)))
890 return FALSE;
891
892 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
893 {
895 if (Interface->HasAlternateSettings)
896 Interface->NeedsSetInterface = TRUE;
897
898 for (Index = 0; Index < Interface->PipeCount; Index++)
899 {
900 Pipe = &Interface->Pipes[Index];
901
902 if (Pipe->ZeroBandwidth)
903 {
904 Pipe->State = PipeState::Disabled;
905 Child->m_EndpointsUnchanged[Child->m_UnchangedCount++] = Pipe->Endpoint;
906 }
907 else
908 {
909 Pipe->State = PipeState::PendingEnable;
910 Child->m_EndpointsToEnable[Child->m_EnableCount++] = Pipe->Endpoint;
911 }
912 }
913 }
914
915 return TRUE;
916}
917
918/* Handles back to the client */
919
920static
922NTAPI
926{
927 PUCXHUB_STACK_INTERFACE Stack = &Child->m_Hub->m_Stack;
928
929 Pipe->PipeHandle = Stack->EndpointGetPipeHandle(Pipe->Endpoint);
930 if (Pipe->PipeHandle == NULL)
931 DPRINT1("Endpoint 0x%x has no pipe handle\n", Pipe->Descriptor->bEndpointAddress);
932
933 Stack->MarkEndpointClientOwned(Pipe->Endpoint);
934 return Pipe->PipeHandle;
935}
936
937/* The interface list was built in URB order, so both are walked side by side */
938VOID
940{
942 HubConfiguration* Config = Child->m_CurrentConfig;
944 PUSBD_INTERFACE_INFORMATION Info = &Urb->UrbSelectConfiguration.Interface;
946 HubPipe* Pipe;
948 ULONG Index;
949
950 if (Config == NULL)
951 return;
952
953 for (Entry = Config->Interfaces.Flink;
954 Entry != &Config->Interfaces;
956 {
958
959 for (Index = 0; Index < Interface->PipeCount; Index++)
960 {
961 Pipe = &Interface->Pipes[Index];
962
963 Info->Pipes[Index].PipeHandle = HubChildExposePipe(Child, Pipe);
964 Info->Pipes[Index].MaximumTransferSize =
965 Child->m_Hub->m_Stack.EndpointGetMaxTransferSize(Pipe->Endpoint);
966 }
967 }
968}
969
970/* MaximumTransferSize is left alone on SELECT_INTERFACE */
971VOID
973{
975 HubConfiguration* Config = Child->m_CurrentConfig;
977 PUSBD_INTERFACE_INFORMATION Info = &Urb->UrbSelectInterface.Interface;
980 ULONG Index;
981
982 if (Config == NULL)
983 return;
984
985 for (Entry = Config->Interfaces.Flink; Entry != &Config->Interfaces; Entry = Entry->Flink)
986 {
988 if (Interface->Descriptor->bInterfaceNumber != Info->InterfaceNumber)
989 continue;
990
991 for (Index = 0; Index < Interface->PipeCount; Index++)
992 Info->Pipes[Index].PipeHandle = HubChildExposePipe(Child, &Interface->Pipes[Index]);
993
994 return;
995 }
996
997 DPRINT1("Device %p selected interface %u is not in the configuration\n", Child, Info->InterfaceNumber);
998}
WCHAR Second[]
Definition: FormatMessage.c:12
WCHAR First[]
Definition: FormatMessage.c:11
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
USBD_STATUS NTAPI HubNtStatusToUsbd(_In_ NTSTATUS Status)
Definition: childpdo.cpp:190
Definition: ehthrow.cxx:93
Definition: ehthrow.cxx:54
HubChild * m_Device
Definition: devsm.h:1832
VOID SetConfigInfoInRequest()
Definition: devconfig.cpp:939
BOOLEAN PrepareConfigLists()
Definition: devconfig.cpp:557
VOID SetInterfaceInfoInRequest()
Definition: devconfig.cpp:972
BOOLEAN PrepareListsForReset()
Definition: devconfig.cpp:872
BOOLEAN PrepareInterfaceLists()
Definition: devconfig.cpp:706
_Out_ PKIRQL Irql
Definition: csq.h:179
PUCHAR End
Definition: desccheck.cpp:2229
PUSB_INTERFACE_DESCRIPTOR NTAPI HubDescFindInterface(_In_ PUSB_CONFIGURATION_DESCRIPTOR Config, _In_ PVOID Position, _In_ LONG Number, _In_ LONG Alternate, _In_ LONG Class, _In_ LONG SubClass, _In_ LONG Protocol, _Out_opt_ PBOOLEAN HasAlternates)
Definition: desccheck.cpp:3371
BosWalk Walk
Definition: desccheck.cpp:2225
#define COMPANION_LENGTH
Definition: devconfig.cpp:22
static NTSTATUS NTAPI HubInterfacesShareEndpoints(_In_ HubInterface *First, _In_ HubInterface *Second)
Definition: devconfig.cpp:509
static NTSTATUS NTAPI HubAllocateInterface(_In_ PUSB_INTERFACE_DESCRIPTOR Descriptor, _In_ BOOLEAN HasAlternates, _Out_ HubInterface **Result)
Definition: devconfig.cpp:207
VOID NTAPI HubChildCollectForDisable(_In_ HubChild *Child, _In_ HubInterface *Interface)
Definition: devconfig.cpp:132
static VOID NTAPI HubChildRecordFailure(_In_ HubChild *Child, _In_ NTSTATUS Status)
Definition: devconfig.cpp:544
static VOID NTAPI HubChildFreeEndpointArrays(_In_ HubChild *Child)
Definition: devconfig.cpp:70
static NTSTATUS NTAPI HubAllocateConfiguration(_In_ PUSB_CONFIGURATION_DESCRIPTOR Source, _Out_ HubConfiguration **Result)
Definition: devconfig.cpp:170
static NTSTATUS NTAPI HubConfigCheckDuplicates(_In_ HubConfiguration *Config)
Definition: devconfig.cpp:463
#define SSP_COMPANION_LENGTH
Definition: devconfig.cpp:23
static NTSTATUS NTAPI HubChildInitPipes(_In_ HubChild *Child, _Inout_ PUSBD_INTERFACE_INFORMATION Info, _Inout_ HubInterface *Interface, _In_ PUCHAR Walk, _In_ PUCHAR End)
Definition: devconfig.cpp:328
#define BCD_USB_25
Definition: devconfig.cpp:19
static BOOLEAN NTAPI HubConfigHasEndpointZero(_In_ HubConfiguration *Config)
Definition: devconfig.cpp:442
FORCEINLINE BOOLEAN NTAPI HubTypeFits(_In_ PUCHAR Walk, _In_ PUCHAR End)
Definition: devconfig.cpp:269
static VOID NTAPI HubFreeConfiguration(_In_ HubChild *Child, _In_ HubConfiguration *Config)
Definition: devconfig.cpp:248
#define CLIENT_INTERVAL_CAP
Definition: devconfig.cpp:16
static BOOLEAN NTAPI HubInterfaceHasEndpointZero(_In_ HubInterface *Interface)
Definition: devconfig.cpp:425
static USBD_PIPE_HANDLE NTAPI HubChildExposePipe(_In_ HubChild *Child, _Inout_ HubPipe *Pipe)
Definition: devconfig.cpp:923
static PURB NTAPI HubChildClientUrb(_In_ HubChild *Child)
Definition: devconfig.cpp:29
static NTSTATUS NTAPI HubChildSizeEndpointArrays(_In_ HubChild *Child, _In_ ULONG Count)
Definition: devconfig.cpp:94
static VOID NTAPI HubPickCompanions(_In_ HubPipe *Pipe, _Inout_ PUSBD_PIPE_INFORMATION Client, _In_ PUCHAR Walk, _In_ PUCHAR End)
Definition: devconfig.cpp:280
static BOOLEAN NTAPI HubChildSettingFiltered(_In_ HubChild *Child, _In_ UCHAR InterfaceNumber, _In_ UCHAR AlternateSetting)
Definition: devconfig.cpp:43
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#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 A(row, col)
#define B(row, col)
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
Status
Definition: gdiplustypes.h:24
HubAltSettingFilter * Filter
_Must_inspect_result_ _In_ UCXUSBDEVICE _In_ ULONG _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR Companion
Definition: hubucx.h:308
_In_ UCXHUB_DEVICE_CONTEXT _In_ UCXENDPOINT Endpoint
Definition: hubucx.h:238
#define HUB_TAG_DEVICE
Definition: hubutil.h:13
ULONG Total
Definition: hubwmi.cpp:548
#define I(s)
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
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_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
unsigned short USHORT
Definition: pedump.c:61
@ Other
Definition: video.h:273
#define STATUS_SUCCESS
Definition: shellext.h:65
PACPI_METHOD_ARGUMENT Next
Definition: slotdev.cpp:96
#define DPRINT
Definition: sndvol32.h:73
Definition: client.c:31
ULONG PipeCount
Definition: hubchild.h:189
LIST_ENTRY Link
Definition: hubchild.h:187
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PFN_UCXHUB_ENDPOINT_PIPE_HANDLE EndpointGetPipeHandle
Definition: hubucx.h:443
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
Definition: usb.h:321
USBD_INTERFACE_INFORMATION Interface
Definition: usb.h:323
USBD_CONFIGURATION_HANDLE ConfigurationHandle
Definition: usb.h:322
Definition: usb.h:565
#define max(a, b)
Definition: svc.c:63
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#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
_In_ UCXUSBDEVICE _In_ ULONG Interface
Definition: ucxusbdevice.h:428
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usb100.h:53
#define USB_ENDPOINT_TYPE_CONTROL
Definition: usb100.h:62
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
struct _USB_ENDPOINT_DESCRIPTOR * PUSB_ENDPOINT_DESCRIPTOR
#define USB_ENDPOINT_TYPE_MASK
Definition: usb100.h:61
#define USB_ENDPOINT_DIRECTION_IN(x)
Definition: usb100.h:76
#define USB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR_TYPE
Definition: usb300.h:20
#define USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR_TYPE
Definition: usb300.h:19
struct _USB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR * PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR
struct _USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR * PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR
#define USB_ENDPOINT_ADDRESS_MASK
Definition: usb300.h:64
struct _USBD_INTERFACE_INFORMATION * PUSBD_INTERFACE_INFORMATION
struct _USBD_PIPE_INFORMATION USBD_PIPE_INFORMATION
enum _USBD_PIPE_TYPE USBD_PIPE_TYPE
PVOID USBD_INTERFACE_HANDLE
Definition: usb.h:243
#define USBD_PF_CHANGE_MAX_PACKET
Definition: usb.h:281
#define USBD_STATUS_INTERFACE_NOT_FOUND
Definition: usb.h:218
#define USBD_STATUS_BAD_ENDPOINT_ADDRESS
Definition: usb.h:239
#define USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR
Definition: usb.h:214
_In_ PVOID _In_ LONG _In_ LONG AlternateSetting
Definition: usbdlib.h:197
_In_ PVOID _In_ LONG InterfaceNumber
Definition: usbdlib.h:196
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
Definition: usbdlib.h:333
USHORT Count
Definition: userreq.cpp:200
WdfObjectDelete(String)
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
_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
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
#define FORCEINLINE
Definition: wdftypes.h:67
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
_In_ WDFUSBPIPE Pipe
Definition: wdfusb.h:1741
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409