ReactOS 0.4.17-dev-1281-g065abb3
ucxlink.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: Hub level requests to the USB controller extension
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/* Room for every SuperSpeedPlus speed a root port can report */
14#define HUB_ROOT_PORT_MAX_SPEEDS 48
15
16/* What the hub promises to need on its control pipe while paging */
17#define HUB_FORWARD_PROGRESS_CONTROL 4096
18
19/* Hub class code and the protocol of a multi TT hub interface */
20#define HUB_INTERFACE_CLASS 9
21#define HUB_PROTOCOL_MULTI_TT 2
22
23static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubRootHubInfoComplete;
24static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubIoctlComplete;
25static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubRoot20PortsComplete;
26static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubRoot30PortsComplete;
27static EVT_WDF_REQUEST_COMPLETION_ROUTINE HubControllerHubInfoComplete;
28
29/*
30 * Every hub level request is a fresh WDFREQUEST deleted by its completion.
31 * Any failure before the send reports IoctlFailed right away.
32 */
33static
34VOID
38 _In_ WDFIOTARGET Target,
40 _In_ PVOID Payload,
41 _In_ WDFREQUEST Request,
43{
46
47 RtlZeroMemory(&Stack, sizeof(Stack));
49 Stack.Parameters.DeviceIoControl.IoControlCode = IoControlCode;
50 Stack.Parameters.Others.Argument1 = Payload;
51 WdfRequestWdmFormatUsingStackLocation(Request, &Stack);
52
53 WdfRequestSetCompletionRoutine(Request, Completion, Hub);
54
56 return;
57
58 Status = WdfRequestGetStatus(Request);
59 DPRINT1("Hub %p UCX request 0x%lx not sent 0x%lx\n", Hub, IoControlCode, Status);
60
63}
64
65static
70 _In_ WDFIOTARGET Target,
71 _Out_ WDFREQUEST* Request)
72{
75
77 Attributes.ParentObject = Hub->m_Device;
78
79 *Request = NULL;
80 Status = WdfRequestCreate(&Attributes, Target, Request);
81 if (!NT_SUCCESS(Status))
82 DPRINT1("Hub %p UCX request create failed 0x%lx\n", Hub, Status);
83
84 return Status;
85}
86
87static
88VOID
91 _In_ WDFREQUEST Request,
92 _In_ WDFIOTARGET Target,
95{
97
99
102}
103
104static
105VOID
106NTAPI
108 _In_ WDFREQUEST Request,
109 _In_ WDFIOTARGET Target,
112{
113 if (!NT_SUCCESS(Params->IoStatus.Status))
114 DPRINT1("Hub %p root hub 2.0 port info failed 0x%lx\n", Context, Params->IoStatus.Status);
115
117}
118
119static
120VOID
121NTAPI
123 _In_ WDFREQUEST Request,
124 _In_ WDFIOTARGET Target,
127{
128 if (!NT_SUCCESS(Params->IoStatus.Status))
129 DPRINT1("Hub %p root hub 3.0 port info failed 0x%lx\n", Context, Params->IoStatus.Status);
130
132}
133
134static
135VOID
136NTAPI
138 _In_ WDFREQUEST Request,
139 _In_ WDFIOTARGET Target,
142{
143 if (!NT_SUCCESS(Params->IoStatus.Status))
144 DPRINT1("Hub %p hub info update in UCX failed 0x%lx\n", Context, Params->IoStatus.Status);
145
147}
148
149VOID
151{
152 /* A hub with the full size stack interface gets the 8 byte aligned layout */
154}
155
156/* The root hub reports its ports, latencies and status change pipe */
157static
158VOID
159NTAPI
161 _In_ WDFREQUEST Request,
162 _In_ WDFIOTARGET Target,
165{
167 BOOLEAN Succeeded = NT_SUCCESS(Params->IoStatus.Status);
168
170
171 if (Succeeded)
172 {
176 DPRINT("Hub %p root hub has %u 2.0 and %u 3.0 ports\n",
178 }
179 else
180 {
181 DPRINT1("Hub %p root hub info failed 0x%lx\n", Hub, Params->IoStatus.Status);
182 }
183
186}
187
188VOID
190{
191 WDFIOTARGET Target = WdfDeviceGetIoTarget(m_Hub->m_Device);
192 WDFREQUEST Request;
193
195 {
196 m_Hub->Post(HubEvent::IoctlFailed);
197 return;
198 }
199
201
203 Target,
206 Request,
208}
209
210/* The port info block outlives the request; each call allocates one under the FDO, which frees them */
211VOID
213{
215 WDFIOTARGET Target = WdfDeviceGetIoTarget(m_Hub->m_Device);
217 PROOTHUB_20PORTS_INFO Payload;
219 WDFMEMORY Block = NULL;
220 WDFMEMORY PayloadMemory;
221 WDFREQUEST Request;
223 ULONG Index;
224
225 if (Count == 0)
226 {
228 m_Hub->Post(HubEvent::IoctlDone);
229 return;
230 }
231
233 {
234 m_Hub->Post(HubEvent::IoctlFailed);
235 return;
236 }
237
239 Attributes.ParentObject = m_Hub->m_Device;
240
241 if (!NT_SUCCESS(WdfMemoryCreate(&Attributes,
244 Count * (sizeof(ROOTHUB_20PORT_INFO) + sizeof(PVOID)),
245 &Block,
246 &Buffer)))
247 {
248 DPRINT1("Hub %p no memory for %lu root 2.0 ports\n", m_Hub, Count);
249 goto Failed;
250 }
251
254
255 for (Index = 0; Index < Count; Index++)
256 {
258 Entries[Index].MinorRevision = 0;
259 Entries[Index].HubDepth = 0;
260 }
261
263 Attributes.ParentObject = Request;
264
265 if (!NT_SUCCESS(WdfMemoryCreate(&Attributes,
268 sizeof(*Payload),
269 &PayloadMemory,
270 (PVOID*)&Payload)))
271 {
272 DPRINT1("Hub %p no memory for the 2.0 port info request\n", m_Hub);
273 goto Failed;
274 }
275
276 Payload->Size = sizeof(*Payload);
277 Payload->NumberOfPorts = (USHORT)Count;
278 Payload->PortInfoSize = sizeof(*Entries);
280
282 return;
283
284Failed:
286 if (Block != NULL)
287 {
290 }
291 m_Hub->Post(HubEvent::IoctlFailed);
292}
293
294/* Like the 2.0 request, with room for each port's SuperSpeedPlus speeds */
295VOID
297{
299 WDFIOTARGET Target = WdfDeviceGetIoTarget(m_Hub->m_Device);
301 PROOTHUB_30PORTS_INFO Payload;
304 WDFMEMORY Block = NULL;
305 WDFMEMORY PayloadMemory;
306 WDFREQUEST Request;
308 ULONG Index;
309
310 if (Count == 0)
311 {
313 m_Hub->Post(HubEvent::IoctlDone);
314 return;
315 }
316
318 {
319 m_Hub->Post(HubEvent::IoctlFailed);
320 return;
321 }
322
324 Attributes.ParentObject = m_Hub->m_Device;
325
326 if (!NT_SUCCESS(WdfMemoryCreate(&Attributes,
329 Count * (sizeof(PVOID) + sizeof(ROOTHUB_30PORT_INFO_EX) +
330 HUB_ROOT_PORT_MAX_SPEEDS * sizeof(*Speeds)),
331 &Block,
332 &Buffer)))
333 {
334 DPRINT1("Hub %p no memory for %lu root 3.0 ports\n", m_Hub, Count);
335 goto Failed;
336 }
337
341
342 for (Index = 0; Index < Count; Index++)
343 {
345 Entries[Index].Info.MinorRevision = 0;
346 Entries[Index].Info.HubDepth = 0;
347 Entries[Index].Speeds = &Speeds[Index * HUB_ROOT_PORT_MAX_SPEEDS];
348 Entries[Index].SpeedsCount = 0;
349 Entries[Index].MaxSpeedsCount = HUB_ROOT_PORT_MAX_SPEEDS;
350 }
351
353 Attributes.ParentObject = Request;
354
355 if (!NT_SUCCESS(WdfMemoryCreate(&Attributes,
358 sizeof(*Payload),
359 &PayloadMemory,
360 (PVOID*)&Payload)))
361 {
362 DPRINT1("Hub %p no memory for the 3.0 port info request\n", m_Hub);
363 goto Failed;
364 }
365
366 Payload->Size = sizeof(*Payload);
367 Payload->NumberOfPorts = (USHORT)Count;
368 Payload->PortInfoSize = sizeof(*Entries);
370
372 return;
373
374Failed:
376 if (Block != NULL)
377 {
380 }
381 m_Hub->Post(HubEvent::IoctlFailed);
382}
383
384/* Any interface of the configuration with the multi TT hub protocol */
385static
387NTAPI
390{
392 PUCHAR End = Current + Config->wTotalLength;
395
396 while (Current + sizeof(*Common) <= End)
397 {
399 if (Common->bLength == 0)
400 break;
401
403 Current + sizeof(*Interface) <= End)
404 {
406 if (Interface->bInterfaceClass == HUB_INTERFACE_CLASS &&
407 Interface->bInterfaceProtocol == HUB_PROTOCOL_MULTI_TT)
408 {
409 return TRUE;
410 }
411 }
412
413 Current += Common->bLength;
414 }
415
416 return FALSE;
417}
418
419/* External hubs only; TT flags are only ever set */
420VOID
422{
424 PUSBDEVICE_HUB_INFO Payload;
425 WDFMEMORY PayloadMemory;
426 WDFREQUEST Request;
428
430 {
431 m_Hub->Post(HubEvent::IoctlFailed);
432 return;
433 }
434
436 Attributes.ParentObject = Request;
437
438 if (!NT_SUCCESS(WdfMemoryCreate(&Attributes,
441 sizeof(*Payload),
442 &PayloadMemory,
443 (PVOID*)&Payload)))
444 {
445 DPRINT1("Hub %p no memory for the UCX hub info request\n", m_Hub);
447 m_Hub->Post(HubEvent::IoctlFailed);
448 return;
449 }
450
451 RtlZeroMemory(Payload, sizeof(*Payload));
452 Payload->Header.Size = sizeof(*Payload);
453 Payload->Header.Hub = m_Hub->UsbDevice();
454 Payload->Header.UsbDevice = m_Hub->UsbDevice();
455 Payload->NumberOfPorts = Ports;
456
458 {
459 m_Hub->SetFlag(HubFlag::TtHub);
460 Payload->NumberOfTTs = 1;
461
463 {
464 m_Hub->SetFlag(HubFlag::MultiTtHub);
465 Payload->NumberOfTTs = Ports;
466 }
467
469 }
470
471 DPRINT("Hub %p telling UCX of %lu ports, %lu TTs\n", m_Hub, Ports, (ULONG)Payload->NumberOfTTs);
475 Payload,
476 Request,
478}
479
480/* The one pipe the hub needs while paging: its status change pipe */
482VOID
483NTAPI
484HubRequestReservedIo(
485 _In_ HubFdo* Hub)
486{
490
491 PAGED_CODE();
492
493 RtlZeroMemory(&Info, sizeof(Info));
494 Info.Version = 1;
495 Info.Size = sizeof(Info);
496 Info.Device = Hub->UsbDevice();
497 Info.ControlPipeMaxTransferSize = HUB_FORWARD_PROGRESS_CONTROL;
498 Info.NumberOfPipes = 1;
499 Info.Pipes[0].PipeHandle = Hub->m_Interrupt.Pipe;
500 Info.Pipes[0].ReservedTransferLimit = Hub->IsRootHub() ? Hub->m_Interrupt.BitmapMaxBytes
502
504
505 Status = WdfIoTargetSendInternalIoctlOthersSynchronously(Hub->m_RootHubTarget,
506 NULL,
508 &Argument,
509 NULL,
510 NULL,
511 NULL,
512 NULL);
513 if (!NT_SUCCESS(Status))
514 DPRINT1("Hub %p forward progress notification failed 0x%lx\n", Hub, Status);
515}
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
HubFdo * Hub
Definition: bootdev.cpp:261
Definition: bufpool.h:45
Definition: fdo.h:132
UCXHUB_CONTROLLER_INFO_V2 m_ControllerInfo
Definition: fdo.h:371
PUSB_CONFIGURATION_DESCRIPTOR m_ConfigDescriptor
Definition: fdo.h:425
WDFDEVICE m_Device
Definition: fdo.h:349
USB_HUB_DESCRIPTOR Usb20
Definition: fdo.h:419
PROOTHUB_30PORT_INFO_EX * m_Root30Ports
Definition: fdo.h:376
VOID SetFlag(_In_ HubFlag Flag)
Definition: fdo.h:160
UCXHUB_ROOTHUB_INFO m_RootHubInfo
Definition: fdo.h:374
WDFIOTARGET m_RootHubTarget
Definition: fdo.h:368
PROOTHUB_20PORT_INFO * m_Root20Ports
Definition: fdo.h:375
ULONG m_PortCount
Definition: fdo.h:379
VOID Post(_In_ HubEvent Event)
Definition: fdo.h:194
HubInterruptRequest m_Interrupt
Definition: fdo.h:414
UCXHUB_STACK_INTERFACE m_Stack
Definition: fdo.h:356
UCXUSBDEVICE UsbDevice() const
Definition: fdo.h:180
USHORT m_InterruptMaxPacket
Definition: fdo.h:429
HubParentInfo m_ParentInfo
Definition: fdo.h:360
UCXHUB_PARENT_INTERFACE m_Parent
Definition: fdo.h:355
BOOLEAN IsRootHub() const
Definition: fdo.h:174
union HubFdo::@1628 m_HubDescriptor
VOID UpdateControllerHubInfo()
Definition: ucxlink.cpp:421
VOID GetRootHub20Ports()
Definition: ucxlink.cpp:212
VOID GetRootHub30Ports()
Definition: ucxlink.cpp:296
VOID QueryControllerInfo()
Definition: ucxlink.cpp:150
HubFdo * m_Hub
Definition: hubsm.h:574
VOID GetRootHubInfo()
Definition: ucxlink.cpp:189
PUCHAR End
Definition: desccheck.cpp:2229
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG _In_ PVOID Argument
Definition: dispmprt.h:1288
#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 _IRQL_requires_(irql)
Definition: driverspecs.h:229
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define NonPagedPool
Definition: env_spec_w32.h:307
Status
Definition: gdiplustypes.h:24
HubUxdSettings Current
#define IOCTL_UCXHUB_ROOTHUB_GET_20PORT_INFO
Definition: hubucx.h:51
#define IOCTL_UCXHUB_ROOTHUB_GET_30PORT_INFO
Definition: hubucx.h:52
#define IOCTL_UCXHUB_ROOTHUB_GET_INFO
Definition: hubucx.h:50
#define IOCTL_UCXHUB_DEVICE_HUB_INFO
Definition: hubucx.h:57
#define IOCTL_UCXHUB_NOTIFY_FORWARD_PROGRESS
Definition: hubucx.h:69
#define HUB_TAG_HUB
Definition: hubutil.h:12
#define HUB_TAG_PORT
Definition: hubutil.h:14
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
static const ENTRY Entries[]
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
unsigned short USHORT
Definition: pedump.c:61
static PS2_PORT Ports[PS2_PORTS]
Definition: ps2.c:52
@ Failed
Definition: arc.h:88
#define DPRINT
Definition: sndvol32.h:73
USBD_PIPE_HANDLE Pipe
Definition: hubreq.h:72
ULONG BitmapMaxBytes
Definition: hubreq.h:79
USHORT U2ExitLatency
Definition: fdo.h:91
USHORT U1ExitLatency
Definition: fdo.h:90
PROOTHUB_20PORT_INFO * PortInfoArray
Definition: ucxroothub.h:63
PROOTHUB_30PORT_INFO * PortInfoArray
Definition: ucxroothub.h:95
USHORT MaxU2ExitLatency
Definition: ucxroothub.h:44
USHORT MaxU1ExitLatency
Definition: ucxroothub.h:43
USHORT NumberOf20Ports
Definition: ucxroothub.h:41
USHORT NumberOf30Ports
Definition: ucxroothub.h:42
USB_DEVICE_SPEED HubSpeed
Definition: hubucx.h:504
ROOTHUB_INFO Info
Definition: hubucx.h:119
USBD_PIPE_HANDLE InterruptPipe
Definition: hubucx.h:120
PFN_UCXHUB_CONTROLLER_GET_INFO QueryControllerBus
Definition: hubucx.h:456
USHORT wHubCharacteristics
Definition: usb100.h:174
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
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
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
struct _ROOTHUB_30PORT_INFO_EX * PROOTHUB_30PORT_INFO_EX
struct _ROOTHUB_20PORT_INFO * PROOTHUB_20PORT_INFO
_In_ UCXUSBDEVICE _In_ ULONG Interface
Definition: ucxusbdevice.h:428
struct _USB_INTERFACE_DESCRIPTOR * PUSB_INTERFACE_DESCRIPTOR
struct _USB_COMMON_DESCRIPTOR * PUSB_COMMON_DESCRIPTOR
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usb100.h:52
@ UsbHighSpeed
Definition: usb200.h:44
union _USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED * PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED
WdfObjectDelete(String)
PUSBUSER_REQUEST_HEADER Block
Definition: userreq.cpp:697
_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
FORCEINLINE VOID WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(_Out_ PWDF_MEMORY_DESCRIPTOR Descriptor, _In_ PVOID Buffer, _In_ ULONG BufferLength)
Definition: wdfmemory.h:102
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
_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
EVT_WDF_REQUEST_COMPLETION_ROUTINE * PFN_WDF_REQUEST_COMPLETION_ROUTINE
Definition: wdfrequest.h:313
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define WDF_NO_SEND_OPTIONS
Definition: wdftypes.h:109
#define IRP_MJ_INTERNAL_DEVICE_CONTROL