ReactOS 0.4.17-dev-1281-g065abb3
devsm_enum.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS USB Hub Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Device state machine, attach and first enumeration
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "usbhub3.h"
11
12/* GLOBALS ********************************************************************/
13
14static const DsmEvent DeleteDiscards[] =
15{
18};
19
21
22/* Nothing attached yet. Initial state */
24 { NULL, "AwaitingAttach", 0, &DeviceMachine::OnAwaitingAttach, NULL };
25
26/* Done with the device, waiting for the port to delete the machine */
28 { NULL, "AwaitingDelete", 0, NULL, NULL, DeleteDiscards };
29
30/* Runs the enumeration sub machine with a power reference on the hub */
32 { NULL, "Enumerating", SM_STATE_TAKES_REQUESTS,
34
35/* Enumeration sub machine */
37 { NULL, "ClaimingAddressZero", 0,
39
41 { NULL, "CancelingClaimForHub", 0,
43
46
48 { NULL, "AddressingInEnum", 0,
50
52 { NULL, "ReadingDescriptors", 0,
54
56 { NULL, "LinkPowerInEnum", 0,
58
60 { NULL, "UpdatingDevice", SM_STATE_CRITICAL_ONLY,
62
64 { NULL, "ParkedForHubInEnum", SM_STATE_YIELDS_TO_CALLER,
66
67/* FUNCTIONS ******************************************************************/
68
72{
73 if (Event != DsmEvent::PortAttached)
74 return SmUnhandled();
75
76 if (!RegisterWithHub())
77 {
80 }
81
86}
87
90{
93}
94
98{
99 switch (Event)
100 {
101 case DsmEvent::Succeeded:
104
105 case DsmEvent::Failed:
108
109 case DsmEvent::PortDetached:
111 return EndAfterDetach();
112
113 default:
114 return SmUnhandled();
115 }
116}
117
118/* Tell the port, leave the hub and wait to be deleted */
121{
127}
128
129/* Hub events that arrive after the device left the hub mean nothing to it */
130VOID
132{
133 SmDiscardQueued(DsmEvent::HubResumed);
134 SmDiscardQueued(DsmEvent::HubStarted);
135 SmDiscardQueued(DsmEvent::HubSuspending);
136 SmDiscardQueued(DsmEvent::HubStopping);
137 SmDiscardQueued(DsmEvent::HubResumedWithReset);
138 SmDiscardQueued(DsmEvent::HubStoppingAfterSuspend);
139 SmDiscardQueued(DsmEvent::HubResumedInS0);
140}
141
144{
146 return SmHandled();
147}
148
152{
153 switch (Event)
154 {
155 case DsmEvent::PortDetached:
158
159 case DsmEvent::HubStopping:
160 case DsmEvent::HubSuspending:
162
163 case DsmEvent::ControllerIoctlDone:
165
166 case DsmEvent::ControllerIoctlFailed:
167 return EnumRetryOrFail();
168
169 default:
170 return SmUnhandled();
171 }
172}
173
177{
178 switch (Event)
179 {
180 case DsmEvent::ControllerIoctlDone:
182 return EndWith(DsmEvent::PortDetached);
183
184 case DsmEvent::ControllerIoctlFailed:
185 return EndWith(DsmEvent::PortDetached);
186
187 default:
188 return SmUnhandled();
189 }
190}
191
194{
196 return SmHandled();
197}
198
202{
203 switch (Event)
204 {
205 case DsmEvent::ControllerIoctlDone:
208
209 case DsmEvent::PortDetached:
211
212 case DsmEvent::ControllerIoctlFailed:
214
215 default:
216 return SmUnhandled();
217 }
218}
219
220/* Port disable for a hub stop or suspend while the device holds address zero */
224{
225 switch (Event)
226 {
227 case DsmEvent::PortDetached:
229 return EndWith(DsmEvent::PortDetached);
230
231 case DsmEvent::PortDisableDone:
232 case DsmEvent::PortFault:
234 return EnumParkForHub();
235
236 default:
237 return SmUnhandled();
238 }
239}
240
241/* Port disable for a hub stop or suspend */
245{
246 switch (Event)
247 {
248 case DsmEvent::PortDetached:
249 return EndWith(DsmEvent::PortDetached);
250
251 case DsmEvent::PortDisableDone:
252 case DsmEvent::PortFault:
253 return EnumParkForHub();
254
255 default:
256 return SmUnhandled();
257 }
258}
259
262{
265}
266
269{
270 if (!EnumRetriesUsedUp())
272
274}
275
279{
280 switch (Event)
281 {
282 case DsmEvent::TimerFired:
284
285 case DsmEvent::PortDetached:
286 return EnumStopRetryOnDetach();
287
288 case DsmEvent::HubSuspending:
289 case DsmEvent::HubStopping:
290 return EnumStopRetryForHub();
291
292 default:
293 return SmUnhandled();
294 }
295}
296
299{
300 if (StopTimer())
301 return EndWith(DsmEvent::PortDetached);
302
304}
305
309{
310 if (Event != DsmEvent::TimerFired)
311 return SmUnhandled();
312
313 return EndWith(DsmEvent::PortDetached);
314}
315
318{
319 if (StopTimer())
321
323}
324
328{
329 switch (Event)
330 {
331 case DsmEvent::TimerFired:
333
334 case DsmEvent::PortDetached:
336
337 default:
338 return SmUnhandled();
339 }
340}
341
342/* Out of retries: the port is being disabled */
346{
347 switch (Event)
348 {
349 case DsmEvent::PortDetached:
350 return EndWith(DsmEvent::PortDetached);
351
352 case DsmEvent::HubStopping:
353 case DsmEvent::HubSuspending:
355
356 case DsmEvent::PortFault:
357 case DsmEvent::PortDisableDone:
358 return EndWith(DsmEvent::Failed);
359
360 default:
361 return SmUnhandled();
362 }
363}
364
367{
370
373
374 return SmUnhandled();
375}
376
380{
381 switch (Event)
382 {
383 case DsmEvent::Succeeded:
385
386 case DsmEvent::Failed:
388
389 case DsmEvent::PortDetached:
391 return EndWith(DsmEvent::PortDetached);
392
393 case DsmEvent::HubStopping:
394 case DsmEvent::HubSuspending:
397
398 default:
399 return SmUnhandled();
400 }
401}
402
405{
406 if (!EnumRetriesUsedUp())
408
410}
411
415{
416 switch (Event)
417 {
418 case DsmEvent::TimerFired:
420
421 case DsmEvent::PortDetached:
423 return EnumStopRetryOnDetach();
424
425 case DsmEvent::HubSuspending:
426 case DsmEvent::HubStopping:
428 return EnumStopRetryForHub();
429
430 default:
431 return SmUnhandled();
432 }
433}
434
438{
439 switch (Event)
440 {
441 case DsmEvent::HubStopping:
442 case DsmEvent::HubSuspending:
444
445 case DsmEvent::PortDetached:
447 return EndWith(DsmEvent::PortDetached);
448
449 case DsmEvent::PortFault:
450 case DsmEvent::PortDisableDone:
452 return EndWith(DsmEvent::Failed);
453
454 default:
455 return SmUnhandled();
456 }
457}
458
461{
462 return SmCall(&SettingAddress);
463}
464
468{
469 switch (Event)
470 {
471 case DsmEvent::Failed:
473
474 case DsmEvent::Succeeded:
477
478 case DsmEvent::HubStopping:
479 case DsmEvent::HubSuspending:
481
482 case DsmEvent::PortDetached:
484
485 default:
486 return SmUnhandled();
487 }
488}
489
492{
495}
496
499{
501 return EndWith(DsmEvent::PortDetached);
502}
503
507{
508 switch (Event)
509 {
510 case DsmEvent::Succeeded:
512
513 case DsmEvent::Failed:
515
516 case DsmEvent::PortDetached:
518
519 case DsmEvent::HubSuspending:
520 case DsmEvent::HubStopping:
523
524 default:
525 return SmUnhandled();
526 }
527}
528
529/* Port disable for a hub stop or suspend once the device has its address */
533{
534 switch (Event)
535 {
536 case DsmEvent::PortDetached:
538
539 case DsmEvent::PortFault:
540 case DsmEvent::PortDisableDone:
542
543 default:
544 return SmUnhandled();
545 }
546}
547
550{
553
555}
556
560{
561 switch (Event)
562 {
563 case DsmEvent::Failed:
565
566 case DsmEvent::Succeeded:
568
569 default:
570 return SmUnhandled();
571 }
572}
573
576{
578 return SmHandled();
579}
580
584{
585 switch (Event)
586 {
587 case DsmEvent::ControllerIoctlFailed:
588 case DsmEvent::ControllerExitLatencyTooLarge:
590
591 case DsmEvent::ControllerIoctlDone:
592 if (SupportsPdCharging())
594
595 return EndWith(DsmEvent::Succeeded);
596
597 default:
598 return SmUnhandled();
599 }
600}
601
605{
606 switch (Event)
607 {
608 case DsmEvent::TransferDone:
609 return EndWith(DsmEvent::Succeeded);
610
611 case DsmEvent::TransferFailed:
613
614 default:
615 return SmUnhandled();
616 }
617}
618
621{
622 return SmCall(&HubSuspended);
623}
624
628{
629 switch (Event)
630 {
631 case DsmEvent::ResumedWithHub:
632 case DsmEvent::SuspendedAfterHubResume:
633 case DsmEvent::NeedsReenumeration:
636
637 case DsmEvent::HubStoppedHoldingReference:
638 return EnumParkForHub();
639
640 case DsmEvent::PortDetached:
641 return EndWith(DsmEvent::PortDetached);
642
643 case DsmEvent::HubStarted:
646
647 default:
648 return SmUnhandled();
649 }
650}
#define VOID
Definition: acefi.h:82
static const State AtAddressZero
Definition: devsm.h:332
VOID ReleaseAddressZero()
Definition: devhcd.cpp:478
static const State AddressingInEnum
Definition: devsm.h:333
VOID UpdateDeviceInController()
Definition: devhcd.cpp:753
SM_RESULT EnumRetryOrFail()
Definition: devsm_enum.cpp:268
BOOLEAN DeviceProgrammingLost()
Definition: devmisc.cpp:352
static const State AwaitingPort
Definition: devsm.h:222
SM_RESULT CallWait(_In_ const State *Target, _In_ DSM_NEXT Next)
Definition: devsm.cpp:389
SM_RESULT EnterUpdatingDevice()
Definition: devsm_enum.cpp:575
SM_RESULT Zero30CreateDevice()
Definition: devsm_zero.cpp:337
static const State ReportingUnknown
Definition: devsm.h:694
SM_RESULT Zero20FirstResetDone(_In_ DsmEvent Event)
Definition: devsm_zero.cpp:34
SM_RESULT EndDetached()
Definition: devsm.cpp:415
static const State LinkPowerInEnum
Definition: devsm.h:335
SM_RESULT OnAwaitingAttach(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:70
VOID ClaimAddressZero()
Definition: devhcd.cpp:471
SM_RESULT EnterReadingDescriptors()
Definition: devsm_desc.cpp:76
VOID RequestPortDisable()
Definition: hubport.cpp:638
VOID MarkAttachFailed()
Definition: hubchild.cpp:307
BOOLEAN SupportsPdCharging()
Definition: devmisc.cpp:293
SM_RESULT EndAfterDetach()
Definition: devsm_enum.cpp:120
static const State SettingPdCharging
Definition: devsm.h:244
SM_RESULT EnumTimerFlushedOnDetach(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:307
SM_RESULT EnumPortOffAfterFailureHoldingAddressZero(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:436
BOOLEAN StopTimer()
Definition: hubchild.cpp:295
static const State IoctlAfterDetach
Definition: devsm.h:241
static const State Enumerating
Definition: devsm.h:329
SM_RESULT LinkStart()
Definition: devsm_desc.cpp:965
static const State TimerAfterDetach
Definition: devsm.h:242
SM_RESULT EnumRetryDelayEnded(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:277
SM_RESULT DisableAndDelete(_In_ DSM_THEN After)
Definition: devsm.cpp:315
BOOLEAN KindWithin(_In_ ULONG Allowed)
A device with no version or speed known yet passes for any version or speed.
Definition: devsm.cpp:159
SM_RESULT EnumPortOffAfterDelete()
Definition: devsm_enum.cpp:491
static const State CancelingClaimForHub
Definition: devsm.h:331
static const State AwaitingAttach
Definition: devsm.h:327
VOID DereferencePort()
Definition: hubchild.cpp:325
SM_RESULT EnumClaimEndedOnDetach(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:175
BOOLEAN EnumRetriesUsedUp()
Definition: devmisc.cpp:74
SM_RESULT EndWith(_In_ DsmEvent Result)
Definition: devsm.cpp:186
static const State ParkedForHubInEnum
Definition: devsm.h:337
SM_RESULT EnterAddressing()
Definition: devsm_enum.cpp:460
SM_RESULT EnumPortOffForHub(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:243
SM_RESULT EnumStopRetryOnDetach()
Definition: devsm_enum.cpp:298
SM_RESULT CallStep(_In_ DSM_THEN Then)
Definition: devsm.cpp:552
SM_RESULT EnterClaimingAddressZero()
Definition: devsm_enum.cpp:143
SM_RESULT OnCancelingClaimForHub(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:200
BOOLEAN ReferenceHubPower()
Definition: childpdo.cpp:3982
SM_RESULT CallAtPassive(_In_ DSM_THEN Then)
Definition: devsm.cpp:513
VOID CancelControllerIoctl()
Definition: devhcd.cpp:462
VOID ReferenceDevicePower()
Definition: fanout.cpp:1038
SM_RESULT EnumParkForHub()
Definition: devsm_enum.cpp:261
static const State DisablingPort
Definition: devsm.h:221
VOID DereferenceDevicePower()
Definition: fanout.cpp:1044
BOOLEAN RegisterWithHub()
Definition: fanout.cpp:1026
SM_RESULT EnumRetryOrFailHoldingAddressZero()
Definition: devsm_enum.cpp:404
static const State ReadingDescriptors
Definition: devsm.h:334
SM_RESULT OnEnumerating(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:96
VOID DereferenceHubPower()
Definition: childpdo.cpp:4000
static const State ReportingToPnp
Definition: devsm.h:693
SM_RESULT EnumPortOffHoldingAddressZero(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:222
SM_RESULT OnAddressingInEnum(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:466
SM_RESULT EnterCancelingClaim()
Definition: devsm_enum.cpp:193
SM_RESULT EnumTimerFlushedForHub(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:326
SM_RESULT OnClaimingAddressZero(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:150
VOID NotifyPortDetached()
Definition: hubport.cpp:632
static const State ResettingPort
Definition: devsm.h:225
static const State SettingAddress
Definition: devsm.h:472
SM_RESULT OnAtAddressZero(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:378
static const State HubSuspended
Definition: devsm.h:422
static const State UpdatingDevice
Definition: devsm.h:336
SM_RESULT EnumReleaseAndEndDetached()
Definition: devsm_enum.cpp:498
SM_RESULT EnterParkedForHub()
Definition: devsm_enum.cpp:620
SM_RESULT OnUpdatingDevice(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:582
SM_RESULT OnLinkPowerInEnum(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:558
VOID UnregisterFromHub()
Definition: fanout.cpp:1032
SM_RESULT EnterAtAddressZero()
Definition: devsm_enum.cpp:366
SM_RESULT EnterLinkPowerInEnum()
Definition: devsm_enum.cpp:549
VOID ReferencePort()
Definition: hubchild.cpp:319
SM_RESULT Delay(_In_ DSM_DELAY Kind, _In_ DSM_NEXT Next)
Definition: devsm.cpp:291
SM_RESULT EnumStopRetryForHub()
Definition: devsm_enum.cpp:317
VOID StartEnumRetries()
Definition: devmisc.cpp:59
SM_RESULT EnterEnumerating()
Definition: devsm_enum.cpp:89
SM_RESULT EnumRetryDelayEndedHoldingAddressZero(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:413
SM_RESULT EnumPortOffAfterFailure(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:344
VOID MarkAttachSucceeded()
Definition: hubchild.cpp:313
SM_RESULT EnumPdChargingSet(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:603
VOID DiscardHubEvents()
Definition: devsm_enum.cpp:131
SM_RESULT OnReadingDescriptors(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:505
static const State ClaimingAddressZero
Definition: devsm.h:330
SM_RESULT EnumPortOffWithDevice(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:531
static const State AwaitingDelete
Definition: devsm.h:328
SM_RESULT OnParkedForHubInEnum(_In_ DsmEvent Event)
Definition: devsm_enum.cpp:626
VOID SmDiscardQueued(_In_ DsmEvent Ev)
Definition: smengine.h:522
static SM_RESULT SmTransition(_In_ const State *Target)
Definition: smengine.h:194
static SM_RESULT SmCall(_In_ const State *Start)
Definition: smengine.h:209
static SM_RESULT SmUnhandled()
Definition: smengine.h:188
#define DSM_KIND_PORT30
Definition: devsm.h:153
#define DSM_KIND_ANY_SPEED
Definition: devsm.h:151
DsmEvent
Definition: devsm.h:15
@ NoPingResponse
@ LpmSettingChanged
@ PdoReportedMissing
@ DsmDelayEnumRetry
Definition: devsm.h:124
#define DSM_KIND_PORT20
Definition: devsm.h:152
#define DSM_KIND_USB3X
Definition: devsm.h:145
#define DSM_KIND_ANY_PORT
Definition: devsm.h:154
#define DSM_KIND_ANY_VERSION
Definition: devsm.h:146
static const DsmEvent DeleteDiscards[]
Definition: devsm_enum.cpp:14
static const DsmEvent LpmDiscards[]
Definition: devsm_enum.cpp:20
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define _In_
Definition: no_sal2.h:158
#define SM_STATE_TAKES_REQUESTS
Definition: smengine.h:39
#define SM_STATE_YIELDS_TO_CALLER
Definition: smengine.h:42
#define SM_STATE_CRITICAL_ONLY
Definition: smengine.h:41
One state. Handler gets every event the state sees.
Definition: smengine.h:93
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170