ReactOS 0.4.17-dev-1281-g065abb3
pipeio.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS USB Host Controller Extension
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Endpoint reset, abort pipe and static streams request paths
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "ucx01000.h"
9
10#define NDEBUG
11#include <debug.h>
12
13/* Endpoint reset */
14
15VOID
17 _In_ WDFREQUEST Request)
18{
20 Post(EpEvent::HubEndpointReset);
21}
22
23/* Held until the machine is done with the reset, whoever completed the request */
27{
29 Post(EpEvent::EndpointResetDone);
30
32}
33
34/* Abort pipe */
35
41{
42 if (!m_HasMachine || !Post(EpEvent::ClientAbortUrb))
43 {
44 DPRINT1("Endpoint %p abort pipe failed, endpoint is not running\n", m_Handle);
45 return UcxCompleteUrb(Irp,
46 Urb,
49 }
50
52 Post(EpEvent::AbortUrbParked);
53
54 return STATUS_PENDING;
55}
56
62{
63 struct _URB_GET_ISOCH_PIPE_TRANSFER_PATH_DELAYS* Request = &Urb->UrbGetIsochPipeTransferPathDelays;
66
67 if (m_Pipe.TransferType != UcxTransferType::Isochronous)
68 {
69 DPRINT1("Endpoint %p path delay query on a non isoch pipe\n", m_Handle);
71 }
72
74 {
75 DPRINT("Endpoint %p has no path delay callback\n", m_Handle);
77 }
78
79 RtlZeroMemory(&Delays, sizeof(Delays));
81 if (NT_SUCCESS(Status))
82 {
83 Request->MaximumSendPathDelayInMilliSeconds = Delays.MaximumSendPathDelayInMilliSeconds;
84 Request->MaximumCompletionPathDelayInMilliSeconds = Delays.MaximumCompletionPathDelayInMilliSeconds;
85 }
86 else
87 {
88 DPRINT1("Endpoint %p path delay callback failed 0x%lx\n", m_Handle, Status);
89 }
90
92}
93
94/* Static streams */
95
97static
101 _In_ PIRP Irp,
102 _In_ PURB Urb,
104{
106}
107
108/* Leaves nothing behind on failure */
109static
111NTAPI
115 _Outptr_ UcxStaticStreams** StreamsOut)
116{
117 BOOLEAN Verifying = Endpoint->m_Controller->m_DriverVerifierEnabled;
119 UcxStaticStreams* Streams;
120 ULONG Index;
122
123 *StreamsOut = NULL;
124
125 RtlZeroMemory(&Init, sizeof(Init));
126 Init.Endpoint = Endpoint->m_Handle;
127 Init.StreamCount = Count;
128
129 Status = Endpoint->m_Callbacks.StaticStreamsAdd(Endpoint->m_Handle, Count, &Init);
130 if (!NT_SUCCESS(Status))
131 {
132 DPRINT1("Endpoint %p HCD streams add failed 0x%lx\n", Endpoint->m_Handle, Status);
133 if (Init.Created != NULL)
134 WdfObjectDelete(Init.Created);
135 return Status;
136 }
137
138 /* A success without a streams object is a controller driver bug */
139 if (Init.Created == NULL)
140 {
141 DPRINT1("Endpoint %p HCD streams add created no streams object\n", Endpoint->m_Handle);
142 UcxVerifierBreak(Verifying);
144 }
145
146 Streams = UcxStaticStreams::FromHandle(Init.Created);
147 Streams->m_Init = NULL;
148
150 for (Index = 0; NT_SUCCESS(Status) && Index < Count; Index++)
151 {
152 if (!Streams->Stream(Index)->Filled)
154 }
155
156 if (!NT_SUCCESS(Status))
157 {
158 DPRINT1("Endpoint %p HCD did not set every stream, %lu set calls for %lu streams\n",
159 Endpoint->m_Handle, Init.SetInfoCalls, Count);
160 UcxVerifierBreak(Verifying);
161 WdfObjectDelete(Init.Created);
162 return Status;
163 }
164
165 *StreamsOut = Streams;
166 return STATUS_SUCCESS;
167}
168
169/* Only XRBs of 0x602 clients get here; the pipe handle is not validated */
172 _In_ PIRP Irp,
173 _In_ PURB Urb)
174{
176 ULONG Count = Urb->UrbOpenStaticStreams.NumberOfStreams;
177 UcxStaticStreams* Streams;
180
181 if (Irql != PASSIVE_LEVEL)
182 {
183 DPRINT1("Endpoint %p streams open at IRQL %u\n", m_Handle, Irql);
184 if (Client->m_VerifierEnabled)
185 {
188 Irql,
189 (ULONG_PTR)Irp,
190 (ULONG_PTR)Client->m_ClientDeviceObject);
191 }
193 }
194
195 if (!Client->m_StreamsGranted)
196 {
197 DPRINT1("Endpoint %p streams open without a streams grant\n", m_Handle);
198 if (Client->m_VerifierEnabled)
199 {
202 (ULONG_PTR)Irp,
203 (ULONG_PTR)Urb,
204 (ULONG_PTR)Client->m_ClientDeviceObject);
205 }
207 }
208
209 if (Count == 0 || Count > Client->m_GrantedStreams)
210 {
211 DPRINT1("Endpoint %p streams open for %lu streams, %lu granted\n",
212 m_Handle, Count, Client->m_GrantedStreams);
213 if (Client->m_VerifierEnabled)
214 {
217 Client->m_GrantedStreams,
218 Count,
219 (ULONG_PTR)Urb);
220 }
222 }
223
224 if (UcxVerifierWantsFailure(Client->m_VerifierFailEnableStaticStreams))
225 {
227 DPRINT1("Endpoint %p streams open failed by verifier 0x%lx\n", m_Handle, Status);
229 }
230
231 /* One open at a time per endpoint */
233 {
235 DPRINT1("Endpoint %p static streams are already open\n", m_Handle);
236
237 if (Client->m_VerifierEnabled)
238 {
241 (ULONG_PTR)Irp,
242 (ULONG_PTR)Urb,
243 (ULONG_PTR)Client->m_ClientDeviceObject);
244 }
246 }
247
248 Status = UcxCreateStaticStreams(this, Count, &Streams);
249 if (!NT_SUCCESS(Status))
250 {
253 }
254
255 {
257
259 m_Streams = Streams;
260 }
261
263}
264
265/* A close while the root hub sleeps succeeds and leaves the streams in place */
268 _In_ PIRP Irp,
269 _In_ PURB Urb)
270{
273
275 {
276 DPRINT1("Endpoint %p streams close at IRQL %u\n", m_Handle, KeGetCurrentIrql());
278 }
279
280 if (m_Streams == NULL)
281 {
282 DPRINT1("Endpoint %p streams close with no streams open\n", m_Handle);
284 }
285
287}
288
289VOID
291 _In_ WDFREQUEST Request)
292{
294 Post(EpEvent::ClientStreamsEnable);
295}
296
297VOID
299 _In_ WDFREQUEST Request)
300{
302 Post(EpEvent::ClientStreamsDisable);
303}
304
307 _In_ PIRP Irp,
308 _In_ PURB Urb)
309{
310 PUSBD_STREAM_INFORMATION Info = Urb->UrbOpenStaticStreams.Streams;
311 UcxStaticStreams* Streams;
313 ULONG Index;
314
315 if (!NT_SUCCESS(Irp->IoStatus.Status))
316 {
317 DPRINT1("Endpoint %p HCD streams enable failed 0x%lx\n", m_Handle, Irp->IoStatus.Status);
318
319 {
321
322 Streams = m_Streams;
323 m_Streams = NULL;
324 }
325
326 if (Streams != NULL)
327 WdfObjectDelete(Streams->m_Handle);
328 }
329 else
330 {
331 Streams = m_Streams;
332
333 for (Index = 0; Index < Streams->m_StreamCount; Index++)
334 {
335 Entry = Streams->Stream(Index);
336
337 Info[Index].PipeHandle = Entry->Pipe.Handle();
338 Info[Index].StreamID = Entry->StreamId;
339 Info[Index].MaximumTransferSize = Entry->Pipe.MaximumTransferSize;
340 Info[Index].PipeFlags = 0;
341 }
342 }
343
344 /* The machine never saw this open; finish it here */
346 {
350
352 }
353
355 Post(EpEvent::StreamsOpened);
356
358}
359
362 _In_ PIRP Irp)
363{
365 Post(EpEvent::StreamsClosed);
366
368}
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
DECLSPEC_NORETURN VOID NTAPI KeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
Definition: debug.c:485
UcxRootHub * m_RootHub
Definition: hostctl.h:302
IO_CSQ m_AbortPipeCsq
Definition: hostctl.h:306
KSPIN_LOCK m_TopologyLock
Definition: hostctl.h:310
BOOLEAN m_RootHubInD0
Definition: hostctl.h:323
VOID HandleHubReset(_In_ WDFREQUEST Request)
Definition: pipeio.cpp:16
NTSTATUS GetIsochPathDelays(_In_ PIRP Irp, _In_ PURB Urb)
Definition: pipeio.cpp:59
UcxController * m_Controller
Definition: pipe.h:282
UcxEndpointCallbacks m_Callbacks
Definition: pipe.h:289
BOOLEAN m_OpenFailedOnReset
Definition: pipe.h:306
NTSTATUS CloseStaticStreams(_In_ PIRP Irp, _In_ PURB Urb)
Definition: pipeio.cpp:267
BOOLEAN Post(_In_ EpEvent Event)
Definition: pipe.h:255
UcxStaticStreams * m_Streams
Definition: pipe.h:286
NTSTATUS OpenStaticStreamsComplete(_In_ PIRP Irp, _In_ PURB Urb)
Definition: pipeio.cpp:306
VOID HandleClientStreamsDisable(_In_ WDFREQUEST Request)
Definition: pipeio.cpp:298
IO_CSQ_IRP_CONTEXT m_AbortCsqContext
Definition: pipe.h:308
LONG m_StreamsOpenCount
Definition: pipe.h:287
UcxPipe m_Pipe
Definition: pipe.h:284
UCXENDPOINT m_Handle
Definition: pipe.h:281
VOID HandleClientStreamsEnable(_In_ WDFREQUEST Request)
Definition: pipeio.cpp:290
NTSTATUS OpenStaticStreams(_In_ PIRP Irp, _In_ PURB Urb)
Definition: pipeio.cpp:171
BOOLEAN m_HasMachine
Definition: pipe.h:303
NTSTATUS CloseStaticStreamsComplete(_In_ PIRP Irp)
Definition: pipeio.cpp:361
NTSTATUS OnHcdResetDone(_In_ PIRP Irp)
Definition: pipeio.cpp:25
VOID SetPending(_In_ PVOID Pending)
Definition: pipe.h:273
NTSTATUS AbortPipe(_In_ PIRP Irp, _In_ PURB Urb)
Definition: pipeio.cpp:38
WDFDEVICE Pdo() const
Definition: rhub.h:108
UcxStream * Stream(_In_ ULONG Index)
Definition: pipe.h:373
ULONG m_StreamCount
Definition: pipe.h:381
UcxStaticStreamsInit * m_Init
Definition: pipe.h:385
UCXSSTREAMS m_Handle
Definition: pipe.h:380
NTSTATUS NTAPI UcxForwardStreamsUrb(_In_ WDFDEVICE RootHubPdo, _In_ PIRP Irp, _In_ PURB Urb, _In_ UcxController *Controller)
Definition: clientxrb.cpp:212
VOID NTAPI UcxCompleteHeldUrbIrp(_In_ PIRP Irp)
Definition: clientxrb.cpp:61
NTSTATUS NTAPI UcxCompleteUrb(_In_ PIRP Irp, _In_ PURB Urb, _In_ NTSTATUS Status, _In_ USBD_STATUS UsbdStatus)
Definition: clientxrb.cpp:23
FORCEINLINE UcxXrbPreamble *NTAPI UcxXrbFromUrb(_In_ PURB Urb)
Definition: clientxrb.h:60
#define UCX_USB3_STREAMS_BAD_COUNT
Definition: clientxrb.h:27
#define UCX_BUGCHECK_USB3
Definition: clientxrb.h:22
#define UCX_USB3_STREAMS_IRQL
Definition: clientxrb.h:25
#define UCX_USB3_STREAMS_NOT_GRANTED
Definition: clientxrb.h:26
#define UCX_USB3_STREAMS_OPEN
Definition: clientxrb.h:28
_Out_ PKIRQL Irql
Definition: csq.h:179
NTKERNELAPI VOID NTAPI IoCsqInsertIrp(_Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context)
Insert an IRP into the CSQ.
Definition: csq.c:177
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
Status
Definition: gdiplustypes.h:24
_In_ UCXHUB_DEVICE_CONTEXT _In_ UCXENDPOINT Endpoint
Definition: hubucx.h:238
_In_ PIRP Irp
Definition: kse.h:79
#define _Outptr_
Definition: no_sal2.h:262
#define _In_
Definition: no_sal2.h:158
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:559
static NTSTATUS NTAPI UcxFailStreamsUrb(_In_ PIRP Irp, _In_ PURB Urb, _In_ NTSTATUS Status)
Definition: pipeio.cpp:100
static NTSTATUS NTAPI UcxCreateStaticStreams(_In_ UcxEndpoint *Endpoint, _In_ ULONG Count, _Outptr_ UcxStaticStreams **StreamsOut)
Definition: pipeio.cpp:112
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
Definition: client.c:31
PFN_UCX_ENDPOINT_GET_ISOCH_TRANSFER_PATH_DELAYS GetIsochTransferPathDelays
Definition: pipe.h:87
UcxTransferType TransferType
Definition: pipe.h:33
BOOLEAN Filled
Definition: pipe.h:344
UcxUsbdHandle * Handle
Definition: clientxrb.h:39
Definition: usb.h:565
#define STATUS_PENDING
Definition: telnetd.h:14
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
BOOLEAN NTAPI UcxVerifierWantsFailure(_In_ ULONG Setting)
Definition: ucxutil.cpp:71
NTSTATUS NTAPI UcxRandomErrorStatus(VOID)
Definition: ucxutil.cpp:93
FORCEINLINE VOID NTAPI UcxVerifierBreak(_In_ BOOLEAN Verifying)
Definition: ucxutil.h:168
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
USBD_STATUS NTAPI UcxNtStatusToUsbdStatus(_In_ NTSTATUS Status)
Definition: urbroute.cpp:53
#define USBD_STATUS_SUCCESS
Definition: usb.h:177
#define USBD_STATUS_NOT_SUPPORTED
Definition: usb.h:213
#define USBD_STATUS_INVALID_PARAMETER
Definition: usb.h:203
_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
#define NT_ASSERT
Definition: rtlfuncs.h:3334