ReactOS 0.4.17-dev-1281-g065abb3
devsm_stopped.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, enumerated device whose PDO is not started
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "usbhub3.h"
11
12/* GLOBALS ********************************************************************/
13
15
16/* PDO reported but not started; the device may be disabled if no driver loads in time */
21
22/* No driver came; the device stays enabled and is reset on the next start */
24 { NULL, "StoppedReady", SM_STATE_TAKES_REQUESTS,
26
27/* PDO stopped with the device disabled in the controller and at its port */
29 { NULL, "Stopped", SM_STATE_TAKES_REQUESTS,
31
32/* Stopped while the hub is suspended */
34 { NULL, "StoppedHubSuspended", SM_STATE_TAKES_REQUESTS,
36
37/* Enumerated but not started while the hub is suspended */
39 { NULL, "StoppedEnumeratedHubSuspended", SM_STATE_TAKES_REQUESTS,
42
43/* Reads the product name for a device text query; m_Resume says where to go after */
45 { NULL, "ReadingDeviceText", 0,
47
48/* Sub machine: waits for PnP to ask for the Microsoft OS extension install */
50 { NULL, "AwaitingMsOsInstall", SM_STATE_YIELDS_TO_CALLER,
52
53/* Sets the U2 timeout of an enumerated SuperSpeed device; m_Resume says where to go after */
55 { NULL, "SettingU2Timeout", 0,
57
58/* FUNCTIONS ******************************************************************/
59
60/* Run Then from a state entered after the current one is left */
63 _In_ DSM_THEN Next)
64{
65 m_Then = Next;
66 return SmTransition(&Starting);
67}
68
71{
73}
74
78{
81}
82
85{
87}
88
89/* STOPPED ENUMERATED *********************************************************/
90
93{
96}
97
101{
102 switch (Event)
103 {
104 case DsmEvent::TimerFired:
105 if (DisableWhenUnused())
107
109 return SmTransition(&StoppedReady);
110
111 case DsmEvent::HubStopping:
113
114 case DsmEvent::PortDetached:
115 return DetachUnconfigured();
116
117 case DsmEvent::ClientUnconfigure:
120
121 case DsmEvent::ClientResetDevice:
123
124 case DsmEvent::ClientSelectConfig:
127
128 case DsmEvent::PdoPreStart:
130
131 case DsmEvent::PdoCleanup:
133
134 case DsmEvent::HubSuspending:
136
137 case DsmEvent::PdoPowerUp:
139
140 case DsmEvent::DeviceTextQuery:
143
144 case DsmEvent::HubGetDescriptor:
148
149 default:
150 return SmUnhandled();
151 }
152}
153
156{
158 AllowIo();
160}
161
164{
167}
168
169/* No driver loaded in time: disable the device and its port */
173{
174 if (Event != DsmEvent::ControllerIoctlDone)
175 return SmUnhandled();
176
178}
179
183{
184 switch (Event)
185 {
186 case DsmEvent::PortDetached:
188
189 case DsmEvent::PortFault:
190 case DsmEvent::PortDisableDone:
191 return SmTransition(&Stopped);
192
193 default:
194 return SmUnhandled();
195 }
196}
197
201{
202 switch (Event)
203 {
204 case DsmEvent::PortDetached:
206 return DetachUnconfigured();
207
208 case DsmEvent::PortFault:
209 case DsmEvent::PortDisableDone:
211
212 default:
213 return SmUnhandled();
214 }
215}
216
220{
221 if (Event != DsmEvent::ControllerIoctlDone)
222 return SmUnhandled();
223
226}
227
231{
232 switch (Event)
233 {
234 case DsmEvent::PortSuspendDone:
236
237 case DsmEvent::PortFault:
240
241 case DsmEvent::PortDetached:
243 return DetachUnconfigured();
244
245 default:
246 return SmUnhandled();
247 }
248}
249
250/* Client asked for no configuration; m_Resume says where the flow goes after */
254{
255 if ((Event != DsmEvent::TransferDone) && (Event != DsmEvent::TransferFailed))
256 return SmUnhandled();
257
259 return BackToUnconfigured();
260}
261
262/* Started PDOs go to the unconfigured D0 state, others back to waiting for a start */
265{
266 if (PdoStarted())
268
270}
271
275{
276 if ((Event != DsmEvent::TransferDone) && (Event != DsmEvent::TransferFailed))
277 return SmUnhandled();
278
279 return (this->*m_Resume)();
280}
281
282/* DEVICE TEXT ****************************************************************/
283
286{
289}
290
294{
295 switch (Event)
296 {
297 case DsmEvent::TransferFailed:
298 break;
299
300 case DsmEvent::TransferDone:
302 break;
303
304 default:
305 return SmUnhandled();
306 }
307
309 return EndWith(DsmEvent::Succeeded);
310}
311
315{
316 if (Event != DsmEvent::Succeeded)
317 return SmUnhandled();
318
319 return (this->*m_Resume)();
320}
321
322/* MICROSOFT OS EXTENSION INSTALL *********************************************/
323
327{
328 if (Event != DsmEvent::PdoInstallMsOsExt)
329 return SmUnhandled();
330
332}
333
336{
337 BOOLEAN wanted = ExtPropertiesWanted();
338
340 if (wanted)
341 {
343 return MsOsInstallDone();
344
347 }
348
351
352 return MsOsInstallDone();
353}
354
357{
360}
361
365{
366 switch (Event)
367 {
368 case DsmEvent::TransferDone:
370 {
373 }
374
375 return MsOsInstallDone();
376
377 case DsmEvent::TransferFailed:
378 return MsOsInstallDone();
379
380 default:
381 return SmUnhandled();
382 }
383}
384
388{
389 switch (Event)
390 {
391 case DsmEvent::TransferDone:
392 if (ExtPropertiesValid())
394
395 return MsOsFreeAndDone();
396
397 case DsmEvent::TransferFailed:
398 return MsOsFreeAndDone();
399
400 default:
401 return SmUnhandled();
402 }
403}
404
407{
409 return MsOsFreeAndDone();
410}
411
414{
416 return MsOsInstallDone();
417}
418
419/* STOPPED ENABLED AND STOPPED ************************************************/
420
424{
425 switch (Event)
426 {
427 case DsmEvent::ClientSelectConfig:
428 case DsmEvent::ClientResetPipe:
429 case DsmEvent::ClientClearStall:
430 case DsmEvent::ClientResetDevice:
431 case DsmEvent::ClientUnconfigure:
432 case DsmEvent::ClientSyncResetPipe:
433 case DsmEvent::ClientSetInterface:
435 return SmHandled();
436
437 case DsmEvent::ClientCyclePort:
439 return SmHandled();
440
441 case DsmEvent::DeviceTextQuery:
443 return SmHandled();
444
445 case DsmEvent::HubGetDescriptor:
447 return SmHandled();
448
449 case DsmEvent::ClientStreams:
451
452 case DsmEvent::PdoPowerUp:
454
455 case DsmEvent::PdoPreStart:
456 AllowIo();
458 return SmTransition(&StoppedReady);
459
460 case DsmEvent::PortDetached:
461 return DetachUnconfigured();
462
463 case DsmEvent::PdoCleanup:
465
466 case DsmEvent::LpmSettingChanged:
469
470 case DsmEvent::HubStopping:
471 case DsmEvent::HubSuspending:
473
474 default:
475 return SmUnhandled();
476 }
477}
478
481{
482 return SmTransition(&StoppedReady);
483}
484
488{
489 if (Event != DsmEvent::ControllerIoctlDone)
490 return SmUnhandled();
491
494}
495
496/* Port off after the device was disabled for a hub stop or suspend */
500{
501 switch (Event)
502 {
503 case DsmEvent::PortDetached:
505
506 case DsmEvent::PortFault:
507 case DsmEvent::PortDisableDone:
510
511 default:
512 return SmUnhandled();
513 }
514}
515
519{
520 switch (Event)
521 {
522 case DsmEvent::ClientResetDevice:
523 case DsmEvent::ClientSyncResetPipe:
524 case DsmEvent::ClientSetInterface:
525 case DsmEvent::ClientClearStall:
526 case DsmEvent::ClientUnconfigure:
527 case DsmEvent::ClientResetPipe:
528 case DsmEvent::ClientSelectConfig:
530 return SmHandled();
531
532 case DsmEvent::DeviceTextQuery:
534 return SmHandled();
535
536 case DsmEvent::HubGetDescriptor:
538 return SmHandled();
539
540 case DsmEvent::ClientCyclePort:
542 return SmHandled();
543
544 case DsmEvent::PdoPowerUp:
546
547 case DsmEvent::HubStopping:
548 case DsmEvent::HubSuspending:
550
551 case DsmEvent::ClientStreams:
552 return ForwardStreams(&Stopped);
553
554 case DsmEvent::PortDetached:
556
557 case DsmEvent::PdoPreStart:
558 return ReenumForPreStart();
559
560 case DsmEvent::PdoCleanup:
562
563 default:
564 return SmUnhandled();
565 }
566}
567
570{
573}
574
575/* STOPPED WITH THE HUB SUSPENDED *********************************************/
576
580{
581 switch (Event)
582 {
583 case DsmEvent::ClientUnconfigure:
584 case DsmEvent::ClientResetPipe:
585 case DsmEvent::ClientSetInterface:
586 case DsmEvent::ClientResetDevice:
587 case DsmEvent::ClientSelectConfig:
588 case DsmEvent::ClientClearStall:
589 case DsmEvent::ClientSyncResetPipe:
591 return SmHandled();
592
593 case DsmEvent::HubGetDescriptor:
595 return SmHandled();
596
597 case DsmEvent::PdoPreStart:
598 AckPreStart();
599 return SmHandled();
600
601 case DsmEvent::DeviceTextQuery:
603 return SmHandled();
604
605 case DsmEvent::ClientCyclePort:
607 return SmHandled();
608
609 case DsmEvent::LpmSettingChanged:
610 return SmHandled();
611
612 case DsmEvent::PdoInstallMsOsExt:
614 return SmHandled();
615
616 case DsmEvent::ResumedWithHub:
617 case DsmEvent::NeedsReenumeration:
618 case DsmEvent::SuspendedAfterHubResume:
620
621 case DsmEvent::HubStoppedHoldingReference:
623
624 case DsmEvent::ClientStreams:
626
627 case DsmEvent::PortDetached:
629
630 case DsmEvent::PdoCleanup:
632
633 case DsmEvent::HubStoppingAfterSuspend:
635
636 case DsmEvent::HubStarted:
638
639 default:
640 return SmUnhandled();
641 }
642}
643
646{
649}
650
653{
655 return SmTransition(&Stopped);
656}
657
661{
662 switch (Event)
663 {
664 case DsmEvent::PortDisableDone:
665 case DsmEvent::PortFault:
666 return SmTransition(&Stopped);
667
668 case DsmEvent::HubStopping:
669 case DsmEvent::HubSuspending:
671
672 case DsmEvent::PortDetached:
674
675 default:
676 return SmUnhandled();
677 }
678}
679
682{
684 return SmCall(&HubSuspended);
685}
686
690{
691 switch (Event)
692 {
693 case DsmEvent::HubGetDescriptor:
695 return SmHandled();
696
697 case DsmEvent::PdoPreStart:
698 AckPreStart();
699 return SmHandled();
700
701 case DsmEvent::PdoInstallMsOsExt:
703 return SmHandled();
704
705 case DsmEvent::HubStoppedHoldingReference:
706 case DsmEvent::HubStopping:
708
709 case DsmEvent::ResumedWithHub:
711
712 case DsmEvent::SuspendedAfterHubResume:
714
715 case DsmEvent::NeedsReenumeration:
716 return ReenumForHubStart();
717
718 case DsmEvent::PortDetached:
719 return DetachUnconfigured();
720
721 case DsmEvent::PdoCleanup:
723
724 default:
725 return SmUnhandled();
726 }
727}
728
732{
733 if (Event != DsmEvent::ControllerIoctlDone)
734 return SmUnhandled();
735
737}
738
742{
743 switch (Event)
744 {
745 case DsmEvent::PortResumeDone:
746 case DsmEvent::PortNowDisabled:
747 case DsmEvent::PortNowEnabledOnReconnect:
749
750 case DsmEvent::PortResumeTimeout:
751 return ReenumForHubStart();
752
753 case DsmEvent::HubStopping:
755
756 case DsmEvent::PortDetached:
757 return DetachUnconfigured();
758
759 case DsmEvent::PortFault:
761
762 case DsmEvent::HubSuspending:
764
765 default:
766 return SmUnhandled();
767 }
768}
769
773{
774 switch (Event)
775 {
776 case DsmEvent::PortResumeDone:
777 case DsmEvent::PortNowDisabled:
778 case DsmEvent::PortNowEnabledOnReconnect:
780
781 case DsmEvent::PortFault:
782 case DsmEvent::PortResumeTimeout:
784
785 case DsmEvent::PortDetached:
786 return DetachUnconfigured();
787
788 default:
789 return SmUnhandled();
790 }
791}
792
796{
797 switch (Event)
798 {
799 case DsmEvent::PortFault:
800 case DsmEvent::PortResumeTimeout:
802
803 case DsmEvent::PortResumeDone:
805
806 case DsmEvent::PortDetached:
807 return DetachUnconfigured();
808
809 default:
810 return SmUnhandled();
811 }
812}
813
814/* U2 TIMEOUT FOR AN ENUMERATED DEVICE ****************************************/
815
818{
821
822 return (this->*m_Resume)();
823}
824
828{
829 switch (Event)
830 {
831 case DsmEvent::Succeeded:
832 case DsmEvent::Failed:
833 return (this->*m_Resume)();
834
835 case DsmEvent::PortDetached:
836 return DetachUnconfigured();
837
838 default:
839 return SmUnhandled();
840 }
841}
842
845{
847 return EndWith(DsmEvent::Succeeded);
848
851}
852
856{
857 switch (Event)
858 {
859 case DsmEvent::PortTimeoutSet:
860 return EndWith(DsmEvent::Succeeded);
861
862 case DsmEvent::PortFault:
863 return EndWith(DsmEvent::Failed);
864
865 default:
866 return SmUnhandled();
867 }
868}
#define VOID
Definition: acefi.h:82
unsigned char BOOLEAN
Definition: actypes.h:127
BOOLEAN m_EndpointsConfigured
Definition: devsm.h:1840
SM_RESULT SelectConfigValidate()
static const State AwaitingMsOsInstall
Definition: devsm.h:840
SM_RESULT StoppedDropPower()
SM_RESULT GoStoppedEnabled()
VOID FailHubDescriptorRequest()
Definition: hubioctl.cpp:383
static const State StoppedAddressed
Definition: devsm.h:834
static const State StoppedEnumeratedHubSuspended
Definition: devsm.h:838
VOID CompletePreStart()
Definition: childpdo.cpp:4045
SM_RESULT StoppedDisabledForHub(_In_ DsmEvent Event)
SM_RESULT MsOsInstallDone()
SM_RESULT MsOsFreeAndDone()
SM_RESULT StoppedPortOffAfterDisable(_In_ DsmEvent Event)
SM_RESULT U2TimeoutSet(_In_ DsmEvent Event)
VOID ConfirmStopWhileSuspended()
Definition: fanout.cpp:1050
static const State AwaitingPort
Definition: devsm.h:222
static const State Starting
Definition: devsm.h:228
SM_RESULT MsOsWriteProperties()
static const State ResumingPort
Definition: devsm.h:236
SM_RESULT OnStoppedHubSuspended(_In_ DsmEvent Event)
SM_RESULT MsOsInstallStart()
SM_RESULT EnterStoppedAddressed()
DSM_THEN m_Resume
Definition: devsm.h:1845
BOOLEAN ProductNameValid()
Definition: devdesc.cpp:803
SM_RESULT OnStoppedEnumeratedHubSuspended(_In_ DsmEvent Event)
VOID RequestPortDisable()
Definition: hubport.cpp:638
SM_RESULT OnStoppedAddressed(_In_ DsmEvent Event)
SM_RESULT EnterSettingU2Timeout()
VOID RequestU2Timeout()
Definition: hubport.cpp:686
BOOLEAN ExtPropertiesWanted()
Definition: hubmsos.cpp:303
SM_RESULT Then(_In_ DSM_THEN Next)
VOID AckPreStart()
Definition: childpdo.cpp:4051
VOID CyclePortForClient()
Definition: childpdo.cpp:4070
SM_RESULT StoppedPortOffAfterHubResume(_In_ DsmEvent Event)
VOID FailClientRequest()
Definition: childpdo.cpp:3558
BOOLEAN ExtPropertiesValid()
Definition: hubmsos.cpp:470
SM_RESULT StoppedResumeEndedForSuspend(_In_ DsmEvent Event)
static const State SuspendingPort
Definition: devsm.h:235
VOID StartDriverWaitTimer()
Definition: childpdo.cpp:4015
SM_RESULT UnconfiguredByClient(_In_ DsmEvent Event)
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 StoppedAckHubStop()
SM_RESULT EnterWithMsOsInstall()
static const State SettingU2Timeout
Definition: devsm.h:841
SM_RESULT ReenumForPreStart()
static const State StoppedReady
Definition: devsm.h:835
VOID SetNullConfiguration()
Definition: devreq.cpp:777
SM_RESULT DeviceTextRead(_In_ DsmEvent Event)
SM_RESULT StoppedPortResumed(_In_ DsmEvent Event)
SM_RESULT OnReadingDeviceText(_In_ DsmEvent Event)
VOID MarkMsOsInstallHandled()
Definition: hubmsos.cpp:368
SM_RESULT EndWith(_In_ DsmEvent Result)
Definition: devsm.cpp:186
SM_RESULT EnterReadingDeviceText()
BOOLEAN MsOs20ValuesWanted()
Definition: hubmsos.cpp:127
SM_RESULT ToAwaitingDetachOrRemove(_In_ BOOLEAN Configured)
static const State DisablingDevice
Definition: devsm.h:243
BOOLEAN SetExtPropertiesSemaphore()
Definition: hubmsos.cpp:374
DSM_THEN m_Then
Definition: devsm.h:1834
SM_RESULT CallStep(_In_ DSM_THEN Then)
Definition: devsm.cpp:552
static const State AwaitingDetachOrRemove
Definition: devsm.h:752
VOID GetDescriptorForHub()
Definition: devreq.cpp:1108
BOOLEAN WriteCustomProperties()
Definition: hubmsos.cpp:522
SM_RESULT StoppedDisabledForCleanup(_In_ DsmEvent Event)
VOID ReferenceDevicePower()
Definition: fanout.cpp:1038
BOOLEAN InstallMsOs20Values()
Definition: hubmsos.cpp:170
static const State DisablingPort
Definition: devsm.h:221
static const State StoppedHubSuspended
Definition: devsm.h:837
VOID ReadExtPropertiesHeader()
Definition: devreq.cpp:681
SM_RESULT OnStopped(_In_ DsmEvent Event)
VOID DereferenceDevicePower()
Definition: fanout.cpp:1044
SM_RESULT U2TimeoutStart()
SM_RESULT StoppedPoweredUp()
VOID AllowIo()
Definition: childpdo.cpp:4078
VOID CompleteClientRequest()
Definition: childpdo.cpp:3462
SM_RESULT EnterHubSuspendedReleasingPower()
BOOLEAN PdoStarted()
Definition: childpdo.cpp:4122
SM_RESULT MsOsExtRead(_In_ DsmEvent Event)
SM_RESULT StoppedAckPreStart()
VOID SignalPnpWaiter()
Definition: childpdo.cpp:4023
SM_RESULT CleanupPortDisabled(_In_ DsmEvent Event)
SM_RESULT DetachUnconfigured()
SM_RESULT HubDescriptorDone(_In_ DsmEvent Event)
SM_RESULT StoppedPortSuspendedForHub(_In_ DsmEvent Event)
SM_RESULT StoppedResumeEndedForStop(_In_ DsmEvent Event)
SM_RESULT StoppedEnabledDisabledForHub(_In_ DsmEvent Event)
SM_RESULT ReportMissingAndLeave()
static const State Configured
Definition: devsm.h:1061
BOOLEAN ExtPropertiesHeaderValid()
Definition: hubmsos.cpp:386
VOID CompleteQueryText()
Definition: childpdo.cpp:4057
SM_RESULT GoStoppedEnumerated()
SM_RESULT ReenumForStart(_In_ DSM_REENUM Kind)
BOOLEAN m_FromConfigured
Definition: devsm.h:1850
static const State HubSuspended
Definition: devsm.h:422
SM_RESULT ReenumForClientUnconfigured()
SM_RESULT BackToUnconfigured()
SM_RESULT EnterParkedForHub()
Definition: devsm_enum.cpp:620
SM_RESULT ForwardStreams(_In_ const State *ReturnTo)
Definition: devsm.cpp:645
SM_RESULT StoppedPortOffForNoDriver(_In_ DsmEvent Event)
SM_RESULT StoppedPortOffForHubStop(_In_ DsmEvent Event)
static const State AwaitingPortYielding
Definition: devsm.h:240
SM_RESULT RemovalDeleteForgetPortOn()
static const State ReadingDeviceText
Definition: devsm.h:839
SM_RESULT AtPassive(_In_ DSM_THEN Then)
Definition: devsm.cpp:177
BOOLEAN DisableWhenUnused()
Definition: devmisc.cpp:331
SM_RESULT CallRequest(_In_ const State *Target, _In_ DSM_ACTION Start, _In_ DSM_NEXT Next)
Definition: devsm.cpp:578
static const State RequestingCritical
Definition: devsm.h:230
VOID ForceResetOnNextStart()
Definition: childpdo.cpp:4090
SM_RESULT MsOsExtHeaderRead(_In_ DsmEvent Event)
SM_RESULT StoppedDisabledForNoDriver(_In_ DsmEvent Event)
VOID ReadProductName()
Definition: devreq.cpp:575
BOOLEAN U2NeededForEnumerated()
Definition: devlpm.cpp:151
static const State Stopped
Definition: devsm.h:836
SM_RESULT OnStoppedReady(_In_ DsmEvent Event)
VOID ReleasePnpWaiter()
Definition: childpdo.cpp:4039
SM_RESULT StoppedHubStarted()
SM_RESULT OnAwaitingMsOsInstall(_In_ DsmEvent Event)
VOID ReadExtProperties()
Definition: devreq.cpp:692
VOID FreeExtPropertiesBuffer()
Definition: hubmsos.cpp:559
VOID SignalQueryText()
Definition: childpdo.cpp:4064
SM_RESULT ReenumForHubStart()
BOOLEAN AllocateExtPropertiesBuffer()
Definition: hubmsos.cpp:411
SM_RESULT OnSettingU2Timeout(_In_ DsmEvent Event)
static const State UnconfiguredOn
Definition: devsm.h:947
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_ANY_SPEED
Definition: devsm.h:151
DsmEvent
Definition: devsm.h:15
@ LpmSettingChanged
@ DsmReenumRestart
Definition: devsm.h:137
@ DsmReenumUnconfigured
Definition: devsm.h:136
#define DSM_KIND_USB3X
Definition: devsm.h:145
#define DSM_KIND_ANY_PORT
Definition: devsm.h:154
static const DsmEvent StoppedLpmDiscards[]
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define _In_
Definition: no_sal2.h:158
PACPI_METHOD_ARGUMENT Next
Definition: slotdev.cpp:96
#define SM_STATE_TAKES_REQUESTS
Definition: smengine.h:39
#define SM_STATE_STOP_TIMER_ON_EXIT
Definition: smengine.h:43
#define SM_STATE_YIELDS_TO_CALLER
Definition: smengine.h:42
One state. Handler gets every event the state sees.
Definition: smengine.h:93
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170