ReactOS 0.4.17-dev-1281-g065abb3
hubchild.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: Device object lifetime, its timer and the device machine hooks
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/* Reference tags; only their addresses matter */
14static const char HubTagDeviceCreate[] = "hub child create";
15static const char HubTagDevice[] = "hub child";
16
17/* Device timer durations in ms */
18#define DEVICE_ENUM_RETRY_TIME 500
19#define DEVICE_POST_RESET_TIME_20 32
20#define DEVICE_POST_RESET_TIME_LONG 100
21#define DEVICE_POST_RESET_TIME_30 15
22#define DEVICE_POST_ADDRESS_TIME 10
23#define DEVICE_DUPLICATE_POLL_TIME 500
24
25/* Language the hub asks strings in until the device says otherwise */
26#define DEVICE_DEFAULT_LANGUAGE 0x0409
27
31{
32 return HubGetChildContext(Object);
33}
34
37{
39 return UsbSuperSpeed;
41 return UsbHighSpeed;
43 return UsbLowSpeed;
44 return UsbFullSpeed;
45}
46
48static
49VOID
53{
54 if (*Object == NULL)
55 return;
56
59 *Object = NULL;
60}
61
62static
63VOID
67{
68 if (Buffer != NULL)
70}
71
72static
77 _Out_ WDFREQUEST* Request)
78{
81
83 Attributes.ParentObject = Port->m_Object;
84
85 Status = WdfRequestCreate(&Attributes, WdfDeviceGetIoTarget(Port->m_Hub->m_Device), Request);
86 if (NT_SUCCESS(Status))
88
89 return Status;
90}
91
92/* Requests, timer and memory hang off the port object, so the device holds its own references to them */
96{
97 HubFdo* Hub = Port->m_Hub;
99 WDF_TIMER_CONFIG TimerConfig;
102 PVOID Payload;
104
106 Attributes.ParentObject = Port->m_Object;
107 Attributes.ExecutionLevel = WdfExecutionLevelPassive;
108 Attributes.EvtDestroyCallback = EvtDestroy;
109
110 Status = WdfObjectCreate(&Attributes, &Object);
111 if (!NT_SUCCESS(Status))
112 {
113 DPRINT1("Port %u device object creation failed 0x%lx\n", Port->Number(), Status);
114 return NULL;
115 }
116
118
119 Child = new (HubGetChildContext(Object)) HubChild();
121 Child->m_Port = Port;
122 Child->m_Hub = Hub;
123
124 if (!Port->HasProperty(PortProperty::Removable))
125 Child->SetProperty(ChildProperty::NotRemovable);
126 else
127 Child->ClearProperty(ChildProperty::NotRemovable);
128
129 DPRINT("Hub %p port %u enumeration starting\n", Hub, Port->Number());
130
131 Status = Child->m_Control.Create(Port->m_Object, WdfDeviceGetIoTarget(Hub->m_Device));
132 if (!NT_SUCCESS(Status))
133 {
134 DPRINT1("Device %p control request creation failed 0x%lx\n", Child, Status);
135 goto Failed;
136 }
138
139 Status = HubCreateDeviceRequest(Port, &Child->m_UcxRequest);
140 if (!NT_SUCCESS(Status))
141 {
142 DPRINT1("Device %p UCX request creation failed 0x%lx\n", Child, Status);
143 goto Failed;
144 }
145
146 Child->m_LanguageId = DEVICE_DEFAULT_LANGUAGE;
147 Child->m_Kind = 0;
148 Child->m_ValidationBitmap.SizeOfBitMap = RTL_BITS_OF(Child->m_ValidationBits);
149 Child->m_ValidationBitmap.Buffer = Child->m_ValidationBits;
150
151 Child->m_Timer.Initialize(TimerFired, Child);
152
155 Attributes.ParentObject = Port->m_Object;
156 Attributes.ExecutionLevel = WdfExecutionLevelPassive;
157
158 Status = WdfTimerCreate(&TimerConfig, &Attributes, &Child->m_BandwidthRetryTimer);
159 if (!NT_SUCCESS(Status))
160 {
161 DPRINT1("Device %p out of bandwidth timer creation failed 0x%lx\n", Child, Status);
162 goto Failed;
163 }
164 WdfObjectReferenceWithTag(Child->m_BandwidthRetryTimer, (PVOID)HubTagDevice);
165
167 KeInitializeEvent(&Child->m_PreStartEvent, NotificationEvent, FALSE);
168 KeInitializeEvent(&Child->m_QueryTextEvent, NotificationEvent, FALSE);
169
170 Child->m_WorkItem = Hub->AllocateWorkItem();
171 if (Child->m_WorkItem == NULL)
172 {
173 DPRINT1("Device %p work item allocation failed\n", Child);
174 goto Failed;
175 }
176
178 Attributes.ParentObject = Port->m_Object;
179
180 Status = WdfMemoryCreate(&Attributes,
183 sizeof(HubUcxPayload),
184 &Child->m_UcxPayloadMemory,
185 &Payload);
186 if (!NT_SUCCESS(Status))
187 {
188 DPRINT1("Device %p UCX payload allocation failed 0x%lx\n", Child, Status);
189 goto Failed;
190 }
191 WdfObjectReferenceWithTag(Child->m_UcxPayloadMemory, (PVOID)HubTagDevice);
192 Child->m_UcxPayload = (HubUcxPayload*)Payload;
193
194 KeInitializeSpinLock(&Child->m_ConfigLock);
195 Child->m_Machine.Initialize(Child);
196
197 Port->m_Child = Child;
198 DPRINT("Port %u created device %p\n", Port->Number(), Child);
199 return Child;
200
201Failed:
203 return NULL;
204}
205
206/* At passive level; the timer callback is waited for */
207VOID
208NTAPI
211{
212 HubChild* Child = HubGetChildContext(Object);
213
214 if (Child->m_Port == NULL)
215 return;
216
217 Child->m_Hub->FlushAndDeleteWorkItem(&Child->m_WorkItem);
218
222 HubFreeIfPresent(Child->m_SerialNumber);
223 HubFreeIfPresent(Child->m_AlternateSettingFilter);
224 HubFreeIfPresent(Child->m_ConfigDescriptor);
225 HubFreeIfPresent(Child->m_LanguageIds);
226 HubFreeIfPresent(Child->m_ProductString);
227 HubFreeIfPresent(Child->m_Bos);
228 HubFreeIfPresent(Child->m_EndpointsToEnable);
229 HubFreeIfPresent(Child->m_EndpointsToDisable);
230 HubFreeIfPresent(Child->m_EndpointsUnchanged);
231
232 HubDropDeviceObject((WDFOBJECT*)&Child->m_Control.Request);
233 HubDropDeviceObject((WDFOBJECT*)&Child->m_UcxRequest);
234
235 Child->m_Timer.Cancel();
236 KeFlushQueuedDpcs();
237
238 HubDropDeviceObject((WDFOBJECT*)&Child->m_BandwidthRetryTimer);
239 HubDropDeviceObject((WDFOBJECT*)&Child->m_UcxPayloadMemory);
240
242}
243
244VOID
245NTAPI
248{
249 ((HubChild*)Context)->Post(DsmEvent::TimerFired);
250}
251
252VOID
253NTAPI
258{
261
262 ((HubChild*)Context)->m_Machine.SmContinueOnPassive();
263}
264
265/* Device machine engine hooks */
266
267VOID
269{
271}
272
273VOID
275{
277}
278
279VOID
281{
284 m_Device,
286}
287
290{
291 return m_Device->m_Timer.Cancel();
292}
293
296{
297 return m_Device->m_Timer.Cancel();
298}
299
300ULONG
302{
303 return m_Device->m_Kind;
304}
305
306VOID
308{
309 m_Device->ClearState(ChildState::AttachSucceeded);
310}
311
312VOID
314{
315 m_Device->SetState(ChildState::AttachSucceeded);
316}
317
318VOID
320{
322}
323
324VOID
326{
328}
329
330/* Device timers */
331
332VOID
334{
335 DPRINT1("Device %p retrying enumeration in %lu ms\n", m_Device, (ULONG)DEVICE_ENUM_RETRY_TIME);
337}
338
339VOID
341{
343}
344
345VOID
347{
349}
350
351VOID
353{
355}
356
357VOID
359{
361}
362
363VOID
365{
367}
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
ULONG DeviceKind()
Definition: hubchild.cpp:301
VOID ReferenceDevice()
Definition: hubchild.cpp:268
VOID QueuePassiveWork()
Definition: hubchild.cpp:280
HubChild * m_Device
Definition: devsm.h:1832
VOID StartSuperSpeedPostResetTimer()
Definition: hubchild.cpp:352
VOID MarkAttachFailed()
Definition: hubchild.cpp:307
VOID StartPostResetTimer()
Definition: hubchild.cpp:340
BOOLEAN StopTimer()
Definition: hubchild.cpp:295
VOID ArmPostAddressTimer()
Definition: hubchild.cpp:358
VOID StartLongPostResetTimer()
Definition: hubchild.cpp:346
VOID StartRetryTimer()
Definition: hubchild.cpp:333
VOID DereferencePort()
Definition: hubchild.cpp:325
VOID ReferencePort()
Definition: hubchild.cpp:319
BOOLEAN CancelStateTimer()
Definition: hubchild.cpp:289
VOID ArmDuplicateDeviceTimer()
Definition: hubchild.cpp:364
VOID MarkAttachSucceeded()
Definition: hubchild.cpp:313
VOID DereferenceDevice()
Definition: hubchild.cpp:274
HubPort * m_Port
Definition: hubchild.h:317
VOID ClearState(_In_ ChildState Flag)
Definition: hubchild.h:274
USB_DEVICE_SPEED Speed() const
Definition: hubchild.cpp:36
PUCXHUB_WORKITEM m_WorkItem
Definition: hubchild.h:337
HubFdo * m_Hub
Definition: hubchild.h:316
WDFOBJECT m_Object
Definition: hubchild.h:315
ULONG m_Kind
Definition: hubchild.h:328
HubTimer m_Timer
Definition: hubchild.h:335
static EVT_WDF_OBJECT_CONTEXT_DESTROY EvtDestroy
Definition: hubchild.h:547
BOOLEAN m_NeedsForwardProgress
Definition: hubchild.h:338
VOID SetState(_In_ ChildState Flag)
Definition: hubchild.h:267
static VOID NTAPI TimerFired(_In_ PVOID Context)
Definition: hubchild.cpp:246
static HubChild * Create(_In_ HubPort *Port)
Definition: hubchild.cpp:94
static UCXHUB_WORKITEM_ROUTINE MachineWorkItem
Definition: hubchild.h:548
static HubChild * FromObject(_In_ WDFOBJECT Object)
Definition: hubchild.cpp:29
Definition: fdo.h:132
WDFDEVICE m_Device
Definition: fdo.h:349
PUCXHUB_WORKITEM AllocateWorkItem()
Definition: fdo.cpp:46
VOID EnqueueWorkItem(_In_ PUCXHUB_WORKITEM WorkItem, _In_ PUCXHUB_WORKITEM_ROUTINE Routine, _In_ PVOID Context, _In_ BOOLEAN ForwardProgress)
Definition: fdo.cpp:54
WDFOBJECT m_Object
Definition: hubport.h:227
VOID Start(_In_ ULONG Milliseconds)
Definition: hubutil.h:104
BOOLEAN Cancel()
Definition: hubutil.h:115
VOID NTAPI HubReleaseTransferState(_In_ HubChild *Child)
Definition: devdesc.cpp:973
#define DSM_KIND_SUPER_SPEED
Definition: devsm.h:150
#define DSM_KIND_LOW_SPEED
Definition: devsm.h:149
#define DSM_KIND_HIGH_SPEED
Definition: devsm.h:147
_In_ ULONG Attributes
Definition: dispmprt.h:1077
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NonPagedPool
Definition: env_spec_w32.h:307
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
Status
Definition: gdiplustypes.h:24
CPPORT Port[4]
Definition: headless.c:38
static const char HubTagDevice[]
Definition: hubchild.cpp:15
#define DEVICE_POST_RESET_TIME_30
Definition: hubchild.cpp:21
#define DEVICE_DUPLICATE_POLL_TIME
Definition: hubchild.cpp:23
static NTSTATUS NTAPI HubCreateDeviceRequest(_In_ HubPort *Port, _Out_ WDFREQUEST *Request)
Definition: hubchild.cpp:75
#define DEVICE_ENUM_RETRY_TIME
Definition: hubchild.cpp:18
#define DEVICE_POST_RESET_TIME_LONG
Definition: hubchild.cpp:20
static VOID NTAPI HubFreeIfPresent(_In_opt_ PVOID Buffer)
Definition: hubchild.cpp:65
#define DEVICE_DEFAULT_LANGUAGE
Definition: hubchild.cpp:26
#define DEVICE_POST_ADDRESS_TIME
Definition: hubchild.cpp:22
static const char HubTagDeviceCreate[]
Definition: hubchild.cpp:14
#define DEVICE_POST_RESET_TIME_20
Definition: hubchild.cpp:19
static VOID NTAPI HubDropDeviceObject(_Inout_ WDFOBJECT *Object)
Definition: hubchild.cpp:51
VOID NTAPI HubIdFreeDeviceIds(_In_ HubChild *Child)
Definition: hubid.cpp:813
VOID NTAPI HubReleaseRegistryState(_In_ HubChild *Child)
EVT_WDF_TIMER HubEvtBandwidthRetryTimer
Definition: hubsvc.h:214
_In_opt_ PVOID _In_ PUCXHUB_WORKITEM WorkItem
Definition: hubucx.h:227
FORCEINLINE VOID NTAPI HubDereferenceDeferred(_In_ WDFOBJECT Object)
Definition: hubutil.h:181
#define HUB_TAG_DEVICE
Definition: hubutil.h:13
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define RTL_BITS_OF(sizeOfArg)
Definition: ntbasedef.h:680
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
@ NotificationEvent
@ Failed
Definition: arc.h:88
#define DPRINT
Definition: sndvol32.h:73
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
@ UsbSuperSpeed
Definition: usb200.h:45
@ UsbHighSpeed
Definition: usb200.h:44
@ UsbLowSpeed
Definition: usb200.h:42
@ UsbFullSpeed
Definition: usb200.h:43
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
WdfObjectDelete(String)
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFDEVICE Child
Definition: wdffdo.h:536
#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
@ WdfExecutionLevelPassive
Definition: wdfobject.h:54
#define WdfObjectReference(Handle)
Definition: wdfobject.h:803
#define WdfObjectReferenceWithTag(Handle, Tag)
Definition: wdfobject.h:806
FORCEINLINE VOID WDF_TIMER_CONFIG_INIT(_Out_ PWDF_TIMER_CONFIG Config, _In_ PFN_WDF_TIMER EvtTimerFunc)
Definition: wdftimer.h:111