ReactOS 0.4.17-dev-1281-g065abb3
portsm_frames.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: Port state machine: called frames for port status reading,
5 * hub power up, resume, suspended ports and D3cold
6 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include "usbhub3.h"
12
13/* GLOBALS ********************************************************************/
14
15#define PSM_YIELDS SM_STATE_YIELDS_TO_CALLER
16#define PSM_CRIT SM_STATE_CRITICAL_ONLY
17#define PSM_PASSIVE SM_STATE_NEEDS_PASSIVE
18
19static const PortEvent FrameGoneOnly[] =
20{
22};
23
25{
27};
28
29static const PortEvent DrainDrops[] =
30{
32};
33
35{
39};
40
42{
47};
48
49/* 2.0 port change: read status, ack every change bit, report the change */
51 { NULL, "ChangeIdle20", PSM_YIELDS, &PortMachine::OnChangeIdle20, NULL, NULL };
52
54 { NULL, "ChangeReading20", PSM_CRIT,
56
58 { NULL, "ChangeAcking20", PSM_CRIT,
60
62 { NULL, "ChangeReporting20", PSM_PASSIVE, NULL, &PortMachine::EnterChangeReporting20, NULL };
63
64/* Interrupt transfer given back, status changes are acked until the hub resets */
66 { NULL, "ChangeParked20", PSM_YIELDS | PSM_PASSIVE,
68
69/* 3.0 port change and its reset and resume flavors */
71 { NULL, "ChangeIdle30", PSM_YIELDS, &PortMachine::OnChangeIdle30, NULL, NULL };
72
74 { NULL, "ChangeChecking30", PSM_YIELDS,
76
78 { NULL, "ResetChangeIdle", PSM_YIELDS, &PortMachine::OnResetChangeIdle, NULL, NULL };
79
81 { NULL, "ResetChangeChecking", PSM_YIELDS,
83
85 { NULL, "ResetPollWait", PSM_CRIT,
87
89 { NULL, "ResetPollChecking", PSM_YIELDS,
91
93 { NULL, "ResumeChangeIdle", PSM_YIELDS, &PortMachine::OnResumeChangeIdle, NULL, NULL };
94
96 { NULL, "ResumeChangeChecking", PSM_YIELDS,
98
99/* 3.0 status reading, ends by returning the change, m_ReadKind picks the ending */
101 { NULL, "StatusReading", PSM_CRIT,
103
105 { NULL, "StatusAcking", PSM_CRIT,
107
109 { NULL, "StatusReporting", PSM_PASSIVE, NULL, &PortMachine::EnterStatusReporting, NULL };
110
112 { NULL, "StatusFailing", PSM_PASSIVE, NULL, &PortMachine::EnterStatusFailing, NULL };
113
114/* Waiting for hub stop or suspend: fail device requests, drain status changes */
117
120
123
125 { NULL, "DrainReading", PSM_CRIT,
127
129 { NULL, "DrainAcking", PSM_CRIT,
131
133 { NULL, "DrainRearming", PSM_PASSIVE, NULL, &PortMachine::EnterDrainRearming, NULL };
134
136 { NULL, "DrainChecking", PSM_YIELDS,
138
139/* Hub start: power the port, wait the power on time, read lost changes */
141 { NULL, "PowerOnSending", PSM_CRIT,
143
145 { NULL, "PowerOnSettling", 0,
147
149 { NULL, "StartReading20", PSM_CRIT,
151
153 { NULL, "StartReadingFirst", PSM_CRIT,
155
157 { NULL, "StartReading30", PSM_YIELDS,
159
161 { NULL, "PowerUpResetHub", PSM_YIELDS,
163
165 { NULL, "PowerUpRearming", PSM_YIELDS | PSM_PASSIVE,
167
168/* 2.0 hub resume */
170 { NULL, "ResumePowering", PSM_CRIT,
172
174 { NULL, "ResumeSettling", 0,
176
178 { NULL, "ResumeReading", PSM_CRIT,
180
182 { NULL, "ResumeAckingConnect", PSM_CRIT,
184
186 { NULL, "ReconnectWait", 0, &PortMachine::OnReconnectWait, NULL, NULL };
187
189 { NULL, "ReconnectReading", PSM_CRIT,
191
193 { NULL, "ReconnectAcking", PSM_CRIT,
195
197 { NULL, "ReconnectRearming", PSM_PASSIVE, NULL, &PortMachine::EnterReconnectRearming, NULL };
198
200 { NULL, "ReconnectFlush", 0, &PortMachine::OnReconnectFlush, NULL, NULL };
201
203 { NULL, "ResumeRereading", PSM_CRIT,
205
206/* 3.0 system resume */
208 { NULL, "SystemResumeReading", PSM_YIELDS,
210
212 { NULL, "SystemReconnectWait", 0, &PortMachine::OnSystemReconnectWait, NULL, NULL };
213
215 { NULL, "SystemResumeRereading", PSM_YIELDS,
217
218/* 2.0 suspended port change */
220 { NULL, "SuspendIdle", PSM_YIELDS, &PortMachine::OnSuspendIdle, NULL, NULL };
221
223 { NULL, "SuspendReading", PSM_CRIT,
225
227 { NULL, "SuspendAcking", PSM_CRIT,
229
231 { NULL, "SuspendRecovery", 0,
233
235 { NULL, "SuspendReporting", PSM_PASSIVE, NULL, &PortMachine::EnterSuspendReporting, NULL };
236
237/* D3cold: the suspended device lost power, wait for it to come back */
240
242 { NULL, "D3PoweredOff", PSM_YIELDS, &PortMachine::OnD3PoweredOff, NULL, NULL };
243
245 { NULL, "D3PoweringUp", 0,
247
249 { NULL, "D3Debouncing", 0,
251
253 { NULL, "D3DebounceFlush", 0, &PortMachine::OnD3DebounceFlush, NULL, FrameRemovedOnly };
254
256 { NULL, "D3FlushThenReturn", 0, &PortMachine::OnD3FlushThenReturn, NULL, FrameRemovedOnly };
257
259 { NULL, "D3ResumeAckWait", PSM_YIELDS,
261
263 { NULL, "D3ReconnectWait", 0,
265
267 { NULL, "D3ReconnectFlush", 0, &PortMachine::OnD3ReconnectFlush, NULL, NULL };
268
269/* 3.0 remote wake programming before the hub suspends */
272
273/* FUNCTIONS ******************************************************************/
274
277{
279 return SmHandled();
280}
281
282/* 2.0 PORT CHANGE ************************************************************/
283
287{
288 if (Event != PortEvent::StatusChanged)
289 return SmUnhandled();
290
293}
294
297 _In_ const State* Acking,
298 _In_ const State* Quiet)
299{
300 switch (PendingChange())
301 {
302 case PsmPendingChange:
303 return SmTransition(Acking);
304
305 case PsmPendingError:
306 return ParkChange20(TRUE);
307
308 default:
309 return SmTransition(Quiet);
310 }
311}
312
315 _In_ BOOLEAN ResetHub)
316{
317 m_ParkResetsHub = ResetHub;
319}
320
324{
325 if (Event == PortEvent::TransferFailed)
326 return ParkChange20(TRUE);
327
328 if (Event == PortEvent::TransferDone)
330
331 return SmUnhandled();
332}
333
337{
338 if (Event == PortEvent::TransferFailed)
339 return ParkChange20(TRUE);
340
341 if (Event == PortEvent::TransferDone)
343
344 return SmUnhandled();
345}
346
349{
350 PortEvent change = NextChange();
351
353 return SmReturn(change);
354}
355
358{
360
361 if (m_ParkResetsHub)
362 {
365 }
366
367 return SmHandled();
368}
369
373{
374 if (Event == PortEvent::StatusChanged)
375 return ParkChange20(FALSE);
376
377 return SmUnhandled();
378}
379
380/* 3.0 PORT CHANGE ************************************************************/
381
384 _In_ READ_KIND Kind)
385{
386 m_ReadKind = Kind;
388 return SmCall(&StatusReading);
389}
390
393{
395}
396
399{
401}
402
406{
407 if (Event == PortEvent::StatusChanged)
409
410 return SmUnhandled();
411}
412
416{
417 switch (Event)
418 {
419 case PortEvent::ChangeError:
420 case PortEvent::ChangeResetBusy:
421 case PortEvent::ChangeResetDone:
422 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
423
424 case PortEvent::ChangeLinkError:
425 return ReturnFromFrame(PortEvent::ChangeConnect);
426
427 case PortEvent::ChangeNone:
428 case PortEvent::ChangeResumed:
429 return SmTransition(&ChangeIdle30);
430
431 default:
432 return SmUnhandled();
433 }
434}
435
439{
440 if (Event == PortEvent::StatusChanged)
442
443 return SmUnhandled();
444}
445
449{
450 switch (Event)
451 {
452 case PortEvent::ChangeNone:
453 case PortEvent::ChangeLinkError:
455
456 case PortEvent::ChangeResumed:
457 case PortEvent::ChangeError:
458 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
459
460 case PortEvent::ChangeResetBusy:
464
465 default:
466 return SmUnhandled();
467 }
468}
469
472{
474 return SmHandled();
475}
476
480{
481 if (Event == PortEvent::ResetPollExpired)
483
484 return SmUnhandled();
485}
486
489{
491}
492
496{
497 switch (Event)
498 {
499 case PortEvent::ChangeLinkError:
500 case PortEvent::ChangeResumed:
501 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
502
503 case PortEvent::ChangeNone:
504 if (LinkInU0())
505 return ReturnFromFrame(PortEvent::ChangeResetDone);
506 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
507
508 case PortEvent::ChangeResetBusy:
510
511 default:
512 return SmUnhandled();
513 }
514}
515
519{
520 if (Event == PortEvent::StatusChanged)
522
523 return SmUnhandled();
524}
525
529{
530 switch (Event)
531 {
532 case PortEvent::ChangeNone:
534
535 case PortEvent::ChangeLinkError:
536 return ReturnFromFrame(PortEvent::ChangeConnect);
537
538 case PortEvent::ChangeError:
539 case PortEvent::ChangeResetBusy:
540 case PortEvent::ChangeResetDone:
541 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
542
543 default:
544 return SmUnhandled();
545 }
546}
547
548/* 3.0 STATUS READING *********************************************************/
549
552{
553 if (m_ReadFresh)
554 {
557 KeepHubAwake();
558 }
559
561 return SmHandled();
562}
563
566{
567 if (m_ReadKind == ReadPlain)
569
572
573 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
574}
575
578{
579 if (m_ReadKind == ReadPlain)
581
583 {
586 }
587
588 return ReturnFromFrame(NextChange());
589}
590
594{
595 if (Event == PortEvent::TransferFailed)
596 return StatusFailed();
597
598 if (Event != PortEvent::TransferDone)
599 return SmUnhandled();
600
601 switch (PendingChange())
602 {
603 case PsmPendingChange:
604 return SmTransition(&StatusAcking);
605
606 case PsmPendingError:
607 return StatusFailed();
608
609 default:
610 return StatusQuiet();
611 }
612}
613
617{
618 if (Event == PortEvent::TransferFailed)
619 return StatusFailed();
620
621 if (Event != PortEvent::TransferDone)
622 return SmUnhandled();
623
624 switch (PendingChange())
625 {
626 case PsmPendingChange:
627 return SmTransition(&StatusAcking);
628
629 case PsmPendingError:
630 return StatusFailed();
631
632 default:
634 }
635}
636
639{
641 return SmReturn(NextChange());
642}
643
646{
648 return SmReturn(PortEvent::ChangeNeedsHubReset);
649}
650
651/* DRAINING *******************************************************************/
652
655{
657 return SmTransition(&DrainIdle);
658}
659
662{
664 return SmTransition(&DrainIdle);
665
667}
668
672{
673 switch (Event)
674 {
675 case PortEvent::DisableRequest:
676 case PortEvent::SuspendRequest:
677 case PortEvent::ResetRequest:
678 case PortEvent::ResumeRequest:
679 return FailDeviceRequest();
680
681 case PortEvent::HibernateRequest:
682 if (m_Usb3)
683 return SmUnhandled();
684 return FailDeviceRequest();
685
686 case PortEvent::WarmResetRequest:
687 if (!m_Usb3)
688 return SmUnhandled();
689 return FailDeviceRequest();
690
691 case PortEvent::StatusChanged:
693
694 default:
695 return SmUnhandled();
696 }
697}
698
702{
703 if (Event == PortEvent::StatusChanged)
705
706 return SmUnhandled();
707}
708
712{
713 if (Event == PortEvent::TransferFailed)
715
716 if (Event != PortEvent::TransferDone)
717 return SmUnhandled();
718
720 return SmTransition(&DrainAcking);
721
723}
724
728{
729 if ((Event == PortEvent::TransferDone) || (Event == PortEvent::TransferFailed))
731
732 return SmUnhandled();
733}
734
737{
739 return DrainDone();
740}
741
745{
746 switch (Event)
747 {
748 case PortEvent::ChangeNone:
749 case PortEvent::ChangeResetDone:
750 case PortEvent::ChangeNeedsHubReset:
751 case PortEvent::ChangeLinkError:
752 case PortEvent::ChangeOverCurrentCleared:
753 case PortEvent::ChangeResetBusy:
754 case PortEvent::ChangeError:
755 case PortEvent::ChangeOverCurrent:
756 case PortEvent::ChangeResumed:
757 case PortEvent::ChangeConnect:
758 return DrainDone();
759
760 default:
761 return SmUnhandled();
762 }
763}
764
765/* HUB START ******************************************************************/
766
770{
771 if (Event == PortEvent::TransferDone)
773
774 if (Event != PortEvent::TransferFailed)
775 return SmUnhandled();
776
778 if (m_Usb3)
779 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
780
782}
783
786{
788 return SmHandled();
789}
790
794{
795 if (Event == PortEvent::TimerExpired)
797
798 return SmUnhandled();
799}
800
804{
805 if (Event == PortEvent::TransferFailed)
806 {
809 }
810
811 if (Event != PortEvent::TransferDone)
812 return SmUnhandled();
813
815 return ReturnFromFrame(LostChange());
816}
817
821{
822 if (Event == PortEvent::TransferFailed)
823 {
825 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
826 }
827
828 if (Event != PortEvent::TransferDone)
829 return SmUnhandled();
830
832}
833
837{
838 switch (Event)
839 {
840 case PortEvent::ChangeError:
841 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
842
843 case PortEvent::ChangeResumed:
844 case PortEvent::ChangeResetDone:
845 case PortEvent::ChangeLinkError:
846 return ReturnFromFrame(PortEvent::ChangeConnect);
847
848 default:
849 return SmUnhandled();
850 }
851}
852
855{
857 return SmHandled();
858}
859
862{
864 return SmHandled();
865}
866
870{
871 if (Event == PortEvent::StatusChanged)
873
874 return SmUnhandled();
875}
876
877/* 2.0 HUB RESUME *************************************************************/
878
881{
884}
885
888{
889 return ReturnFromFrame(LostChange());
890}
891
894{
897
898 return ResumeReadDone();
899}
900
904{
905 if (Event == PortEvent::TransferDone)
907
908 if (Event != PortEvent::TransferFailed)
909 return SmUnhandled();
910
912 return ResumeStateDisabled();
913}
914
918{
919 if (Event == PortEvent::TimerExpired)
921
922 return SmUnhandled();
923}
924
932{
934
935 if (Event == PortEvent::TransferFailed)
936 {
938 return ResumeStateDisabled();
939 }
940
941 if (Event != PortEvent::TransferDone)
942 return SmUnhandled();
943
945
947 if (bits.OverCurrent || bits.OverCurrentChanged)
948 {
950 return ReturnFromFrame(bits.OverCurrent ? PortEvent::ChangeOverCurrent
951 : PortEvent::ChangeOverCurrentCleared);
952 }
953
954 if (DeviceConnected())
955 return ResumeConnectCheck();
956
959}
960
964{
965 if (Event == PortEvent::TransferFailed)
966 return ResumeStateDisabled();
967
968 if (Event == PortEvent::TransferDone)
969 return ResumeReadDone();
970
971 return SmUnhandled();
972}
973
977{
978 switch (Event)
979 {
980 case PortEvent::StatusChanged:
983
984 case PortEvent::HubStopping:
985 if (StopTimer())
986 return ReturnFromFrame(PortEvent::HubStopping);
989
990 case PortEvent::TimerExpired:
992
993 default:
994 return SmUnhandled();
995 }
996}
997
1000{
1004}
1005
1008{
1009 switch (PendingChange())
1010 {
1011 case PsmPendingChange:
1013
1014 case PsmPendingError:
1015 return ReconnectStatusFailed();
1016
1017 default:
1019 }
1020}
1021
1025{
1026 if (Event == PortEvent::TransferDone)
1027 return ReconnectCheck();
1028
1029 if (Event == PortEvent::TransferFailed)
1030 return ReconnectStatusFailed();
1031
1032 return SmUnhandled();
1033}
1034
1038{
1039 if (Event == PortEvent::TransferDone)
1040 return ReconnectCheck();
1041
1042 if (Event == PortEvent::TransferFailed)
1043 return ReconnectStatusFailed();
1044
1045 return SmUnhandled();
1046}
1047
1050{
1052
1053 if (DeviceConnected() && StopTimer())
1054 return ResumeReadDone();
1055
1056 return SmTransition(&ReconnectWait);
1057}
1058
1062{
1063 if (Event != PortEvent::TimerExpired)
1064 return SmUnhandled();
1065
1067 return ReturnFromFrame(PortEvent::HubStopping);
1068
1070}
1071
1075{
1076 if (Event == PortEvent::TransferFailed)
1077 return ResumeStateDisabled();
1078
1079 if (Event != PortEvent::TransferDone)
1080 return SmUnhandled();
1081
1082 if (DeviceConnected())
1083 return ResumeConnectCheck();
1084
1085 return ResumeReadDone();
1086}
1087
1088/* 3.0 SYSTEM RESUME **********************************************************/
1089
1092{
1095 return ReturnFromFrame(PortEvent::ChangeNeedsReset);
1096}
1097
1101{
1102 switch (Event)
1103 {
1104 case PortEvent::ChangeNone:
1106 return ReturnFromFrame(PortEvent::SubDone);
1107
1108 case PortEvent::ChangeResumed:
1110 return ReturnFromFrame(PortEvent::ChangeResumed);
1111
1112 case PortEvent::ChangeConnect:
1113 if (DeviceConnected())
1114 {
1116 return ReturnFromFrame(PortEvent::ChangeResumed);
1117 }
1120
1121 case PortEvent::ChangeResetBusy:
1124 return ReturnFromFrame(PortEvent::ChangeResetBusy);
1125
1126 case PortEvent::ChangeLinkError:
1127 case PortEvent::ChangeResetDone:
1128 return SystemResumeFailed();
1129
1130 case PortEvent::ChangeError:
1131 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
1132
1133 default:
1134 return SmUnhandled();
1135 }
1136}
1137
1141{
1142 switch (Event)
1143 {
1144 case PortEvent::HubStopping:
1145 if (StopTimer())
1146 return ReturnFromFrame(PortEvent::HubStopping);
1149
1150 case PortEvent::StatusChanged:
1151 if (StopTimer())
1155
1156 case PortEvent::TimerExpired:
1157 return ReturnFromFrame(PortEvent::ChangeConnect);
1158
1159 default:
1160 return SmUnhandled();
1161 }
1162}
1163
1167{
1168 switch (Event)
1169 {
1170 case PortEvent::ChangeLinkError:
1171 return SystemResumeFailed();
1172
1173 case PortEvent::ChangeResumed:
1174 case PortEvent::ChangeError:
1175 case PortEvent::ChangeResetDone:
1176 case PortEvent::ChangeResetBusy:
1177 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
1178
1179 case PortEvent::ChangeNone:
1180 return ReturnFromFrame(PortEvent::ChangeConnect);
1181
1182 case PortEvent::ChangeConnect:
1184 return ReturnFromFrame(PortEvent::ChangeResumed);
1185
1186 default:
1187 return SmUnhandled();
1188 }
1189}
1190
1191/* 2.0 SUSPENDED PORT CHANGE **************************************************/
1192
1196{
1197 if (Event != PortEvent::StatusChanged)
1198 return SmUnhandled();
1199
1202}
1203
1207{
1210}
1211
1219{
1221 PortEvent change;
1222
1223 if (Event == PortEvent::TransferFailed)
1224 return ParkChange20(TRUE);
1225
1226 if (Event != PortEvent::TransferDone)
1227 return SmUnhandled();
1228
1229 switch (PendingChange())
1230 {
1231 case PsmPendingChange:
1232 return SmTransition(&SuspendAcking);
1233
1234 case PsmPendingError:
1235 return ParkChange20(TRUE);
1236
1237 default:
1238 break;
1239 }
1240
1241 change = NextChange();
1242 switch (change)
1243 {
1244 case PortEvent::ChangeResetDone:
1245 case PortEvent::ChangeDisabled:
1246 return ReportSuspendChange(PortEvent::ChangeError);
1247
1248 case PortEvent::ChangeError:
1250 if (bits.Connected && !bits.Enabled)
1251 return ReportSuspendChange(PortEvent::ChangeConnect);
1252 return ReportSuspendChange(PortEvent::ChangeError);
1253
1254 case PortEvent::ChangeResumed:
1256
1257 case PortEvent::ChangeOverCurrentCleared:
1258 case PortEvent::ChangeConnect:
1259 case PortEvent::ChangeOverCurrent:
1260 return ReportSuspendChange(change);
1261
1262 default:
1263 SM_BREAK("Port change not valid on a suspended port");
1264 return SmHandled();
1265 }
1266}
1267
1271{
1272 if (Event == PortEvent::TransferFailed)
1273 return ParkChange20(TRUE);
1274
1275 if (Event == PortEvent::TransferDone)
1277
1278 return SmUnhandled();
1279}
1280
1283{
1285 return SmHandled();
1286}
1287
1291{
1292 if (Event == PortEvent::TimerExpired)
1293 return ReportSuspendChange(PortEvent::ChangeResumed);
1294
1295 return SmUnhandled();
1296}
1297
1300{
1301 if (m_SuspendReport == PortEvent::ChangeResumed)
1303
1305
1306 if (m_SuspendReport != PortEvent::ChangeConnect)
1308
1309 if (!D3ColdEnabled())
1310 return ReturnFromFrame(PortEvent::ChangeConnect);
1311
1312 /* The device lost power while suspended, give it time to come back */
1313 if (!DeviceConnected())
1314 return SmTransition(&D3Idle);
1315
1318 return SmTransition(&D3Debouncing);
1319}
1320
1321/* D3COLD *********************************************************************/
1322
1325 _In_ BOOLEAN AfterResume)
1326{
1327 if (DeviceConnected())
1328 {
1330 m_D3AfterResume = AfterResume;
1331 return SmTransition(&D3Debouncing);
1332 }
1333
1334 if (AfterResume)
1335 return ReturnFromFrame(PortEvent::ChangeConnect);
1336
1337 return SmTransition(&D3Idle);
1338}
1339
1342{
1343 if (StopTimer())
1345
1347}
1348
1352{
1353 if (StopTimer())
1354 return D3PendingDone(Pending);
1355
1358}
1359
1363{
1364 switch (Pending)
1365 {
1367 return ReturnFromFrame(PortEvent::ChangeOverCurrent);
1368
1370 return ReturnFromFrame(PortEvent::ChangeOverCurrentCleared);
1371
1372 case D3PendingHubReset:
1373 return ReturnFromFrame(PortEvent::ChangeNeedsHubReset);
1374
1375 case D3PendingReattach:
1376 if (m_Usb3)
1377 {
1379 return ReturnFromFrame(PortEvent::ChangeResumed);
1380 }
1383 return SmTransition(&D3Debouncing);
1384
1385 default:
1386 return ReturnFromFrame(PortEvent::HubStopping);
1387 }
1388}
1389
1393{
1394 switch (Event)
1395 {
1396 case PortEvent::ChangeDisabled:
1397 case PortEvent::ChangeResetDone:
1398 case PortEvent::ChangeError:
1399 case PortEvent::ChangeResumed:
1400 if (m_Usb3)
1401 return SmUnhandled();
1402 return D3ConnectCheck(FALSE);
1403
1404 case PortEvent::ChangeConnect:
1405 if (!m_Usb3)
1406 return D3ConnectCheck(FALSE);
1407 if (!DevicePresent())
1408 return SmTransition(&D3Idle);
1411
1412 case PortEvent::ChangeOverCurrent:
1413 case PortEvent::ChangeOverCurrentCleared:
1414 case PortEvent::HubStopping:
1415 return ReturnFromFrame(Event);
1416
1417 case PortEvent::ChangeNeedsHubReset:
1418 if (!m_Usb3)
1419 return SmUnhandled();
1420 return ReturnFromFrame(Event);
1421
1422 case PortEvent::ResumeRequest:
1423 case PortEvent::DisableRequest:
1426
1427 case PortEvent::HubSuspending:
1429 return SmTransition(&D3PoweredOff);
1430
1431 default:
1432 return SmUnhandled();
1433 }
1434}
1435
1439{
1440 switch (Event)
1441 {
1442 case PortEvent::HubResumedInS0:
1443 return PowerUp(&D3Idle);
1444
1445 case PortEvent::HubResumed:
1446 case PortEvent::HubResumedWithReset:
1447 if (m_Usb3)
1448 {
1450 return PowerUp(&D3Idle);
1451 }
1452 m_D3PowerUpWarm = (Event == PortEvent::HubResumed);
1453 return SmTransition(&D3PoweringUp);
1454
1455 default:
1456 return SmUnhandled();
1457 }
1458}
1459
1462{
1464}
1465
1469{
1470 switch (Event)
1471 {
1472 case PortEvent::ChangeOverCurrent:
1473 case PortEvent::ChangeOverCurrentCleared:
1474 return ReturnFromFrame(Event);
1475
1476 case PortEvent::SubDone:
1477 case PortEvent::ChangeConnect:
1478 case PortEvent::ChangeError:
1479 case PortEvent::ChangeResumed:
1480 case PortEvent::ChangeResetDone:
1481 if (!DeviceConnected())
1482 return ReturnFromFrame(PortEvent::ChangeConnect);
1484 return ReturnFromFrame(PortEvent::ChangeDisabled);
1485
1486 default:
1487 return SmUnhandled();
1488 }
1489}
1490
1494{
1495 switch (Event)
1496 {
1497 case PortEvent::ChangeError:
1498 case PortEvent::ChangeDisabled:
1499 case PortEvent::ChangeConnect:
1500 case PortEvent::ChangeResumed:
1501 case PortEvent::ChangeResetDone:
1502 return D3StopDebounceTimer();
1503
1504 case PortEvent::ChangeOverCurrent:
1506
1507 case PortEvent::ChangeOverCurrentCleared:
1509
1510 case PortEvent::TimerExpired:
1511 if (!m_D3AfterResume)
1514 return ReturnFromFrame(PortEvent::ChangeDisabled);
1515
1516 case PortEvent::HubStopping:
1517 m_D3FlushReturn = PortEvent::HubStopping;
1519
1520 case PortEvent::HubSuspending:
1521 if (m_D3AfterResume)
1522 return SmUnhandled();
1523 m_D3FlushReturn = PortEvent::HubSuspending;
1525
1526 default:
1527 return SmUnhandled();
1528 }
1529}
1530
1534{
1535 switch (Event)
1536 {
1537 case PortEvent::TimerExpired:
1539
1540 case PortEvent::HubStopping:
1541 m_D3FlushReturn = PortEvent::HubStopping;
1543
1544 case PortEvent::HubSuspending:
1545 if (m_D3AfterResume)
1546 return SmUnhandled();
1547 m_D3FlushReturn = PortEvent::HubSuspending;
1549
1550 default:
1551 return SmUnhandled();
1552 }
1553}
1554
1558{
1559 if (Event == PortEvent::TimerExpired)
1561
1562 return SmUnhandled();
1563}
1564
1568{
1569 switch (Event)
1570 {
1571 case PortEvent::ChangeResetDone:
1572 case PortEvent::ChangeResumed:
1573 case PortEvent::ChangeDisabled:
1574 case PortEvent::ChangeError:
1575 if (m_Usb3)
1576 return SmUnhandled();
1577 return D3ConnectCheck(FALSE);
1578
1579 case PortEvent::ChangeConnect:
1580 if (!m_Usb3)
1581 return D3ConnectCheck(FALSE);
1582 if (DevicePresent())
1584 return ReturnFromFrame(PortEvent::ChangeConnect);
1585
1586 case PortEvent::ChangeOverCurrent:
1587 case PortEvent::ChangeOverCurrentCleared:
1588 case PortEvent::HubStopping:
1589 return ReturnFromFrame(Event);
1590
1591 case PortEvent::ChangeNeedsHubReset:
1592 if (!m_Usb3)
1593 return SmUnhandled();
1594 return ReturnFromFrame(Event);
1595
1596 case PortEvent::ResumeRequest:
1597 if (m_Usb3)
1598 return ReturnFromFrame(PortEvent::ChangeResumed);
1600 return ReturnFromFrame(PortEvent::ChangeDisabled);
1601
1602 case PortEvent::DisableRequest:
1603 if (m_Usb3)
1604 return SmUnhandled();
1606 return ReturnFromFrame(PortEvent::ChangeDisabled);
1607
1608 default:
1609 return SmUnhandled();
1610 }
1611}
1612
1616{
1617 switch (Event)
1618 {
1619 case PortEvent::ChangeResumed:
1620 case PortEvent::ChangeError:
1621 case PortEvent::ChangeResetDone:
1622 if (m_Usb3)
1623 return SmUnhandled();
1624 if (DeviceConnected())
1627
1628 case PortEvent::ChangeConnect:
1632
1633 case PortEvent::ChangeDisabled:
1634 if (m_Usb3)
1635 return SmUnhandled();
1637
1638 case PortEvent::ChangeOverCurrent:
1640
1641 case PortEvent::ChangeOverCurrentCleared:
1643
1644 case PortEvent::ChangeNeedsHubReset:
1645 if (!m_Usb3)
1646 return SmUnhandled();
1648
1649 case PortEvent::HubStopping:
1651
1652 case PortEvent::TimerExpired:
1653 return ReturnFromFrame(PortEvent::ChangeConnect);
1654
1655 default:
1656 return SmUnhandled();
1657 }
1658}
1659
1663{
1664 if (Event == PortEvent::TimerExpired)
1665 return D3PendingDone(m_D3Pending);
1666
1667 /* Only the hub stop flush has nothing more to wait for */
1668 if ((Event == PortEvent::HubStopping) && (m_D3Pending != D3PendingStop))
1669 {
1672 }
1673
1674 return SmUnhandled();
1675}
1676
1677/* REMOTE WAKE ****************************************************************/
1678
1681{
1683
1684 if (!enable)
1686
1687 KeepHubAwake();
1689 return SmHandled();
1690}
1691
1695{
1696 if (Event == PortEvent::TransferFailed)
1698 else if (Event != PortEvent::TransferDone)
1699 return SmUnhandled();
1700
1701 return ReturnFromFrame(PortEvent::SubDone);
1702}
unsigned char BOOLEAN
Definition: actypes.h:127
SM_RESULT OnSystemResumeReading(_In_ PortEvent Event)
static const State ChangeIdle30
Definition: portsm.h:284
VOID SendRemoteWake(_In_ BOOLEAN Enable)
Definition: portxfer.cpp:263
SM_RESULT OnReconnectWait(_In_ PortEvent Event)
SM_RESULT OnChangeAcking20(_In_ PortEvent Event)
static const State StartReadingFirst
Definition: portsm.h:309
static const State ResumeRereading
Definition: portsm.h:323
SM_RESULT OnStatusAcking(_In_ PortEvent Event)
SM_RESULT OnResumeAckingConnect(_In_ PortEvent Event)
SM_RESULT OnWakeArming(_In_ PortEvent Event)
SM_RESULT CallStatusRead(_In_ READ_KIND Kind)
static const State DrainIdle
Definition: portsm.h:298
BOOLEAN m_D3AfterResume
Definition: portsm.h:966
@ D3PendingOverCurrentCleared
Definition: portsm.h:188
@ D3PendingStop
Definition: portsm.h:186
@ D3PendingReattach
Definition: portsm.h:189
@ D3PendingOverCurrent
Definition: portsm.h:187
@ D3PendingHubReset
Definition: portsm.h:190
static const State SuspendAcking
Definition: portsm.h:330
SM_RESULT OnResumeReading(_In_ PortEvent Event)
An over-current seen now, or one that came and went while suspended, is reported.
SM_RESULT EnterResetPollChecking()
SM_RESULT OnReconnectFlush(_In_ PortEvent Event)
SM_RESULT ResumeReadDone()
SM_RESULT OnSystemReconnectWait(_In_ PortEvent Event)
SM_RESULT CheckPending20(_In_ const State *Acking, _In_ const State *Quiet)
SM_RESULT EnterPoweringPort()
static const State ResetChangeChecking
Definition: portsm.h:287
SM_RESULT OnD3DebounceFlush(_In_ PortEvent Event)
static const State DrainEmptyIdleUsb2
Definition: portsm.h:299
SM_RESULT OnResetChangeIdle(_In_ PortEvent Event)
SM_RESULT EnterReadingStatus()
SM_RESULT OnDrainIdle(_In_ PortEvent Event)
SM_RESULT EnterStatusReporting()
SM_RESULT EnterD3PoweringUp()
SM_RESULT EnterChangeReporting20()
SM_RESULT OnResetPollWait(_In_ PortEvent Event)
BOOLEAN m_ParkResetsHub
Definition: portsm.h:965
SM_RESULT StatusQuiet()
SM_RESULT EnterSuspendRecovery()
READ_KIND m_ReadKind
Definition: portsm.h:955
static const State ResetPollChecking
Definition: portsm.h:289
static const State D3Idle
Definition: portsm.h:333
static const State ResumeChangeIdle
Definition: portsm.h:290
SM_RESULT EnterPowerUpResetHub()
SM_RESULT OnD3ReconnectWait(_In_ PortEvent Event)
PortEvent m_SuspendReport
Definition: portsm.h:957
static const State ChangeAcking20
Definition: portsm.h:280
BOOLEAN BootDeviceReturning()
Definition: hubport.cpp:558
SM_RESULT EnterPlainStatusRead()
SM_RESULT OnDrainEmptyIdle(_In_ PortEvent Event)
static const State ResumeSettling
Definition: portsm.h:315
SM_RESULT OnD3ReconnectFlush(_In_ PortEvent Event)
SM_RESULT OnChangeIdle20(_In_ PortEvent Event)
SM_RESULT OnResetChangeChecking(_In_ PortEvent Event)
static const State DrainEmptyIdleUsb3
Definition: portsm.h:300
SM_RESULT OnResumeSettling(_In_ PortEvent Event)
static const State PowerUpResetHub
Definition: portsm.h:311
SM_RESULT ReportSuspendChange(_In_ PortEvent Report)
SM_RESULT EnterChangeParked20()
SM_RESULT ResumeConnectCheck()
static const State D3DebounceFlush
Definition: portsm.h:337
static const State PowerUpRearming
Definition: portsm.h:312
VOID SendAckChange()
Definition: portxfer.cpp:167
static const State D3PoweredOff
Definition: portsm.h:334
static const State DrainReading
Definition: portsm.h:301
SM_RESULT StatusFailed()
SM_RESULT OnResumeChangeIdle(_In_ PortEvent Event)
BOOLEAN LinkInU0()
Definition: hubport.cpp:510
BOOLEAN DeviceConnected()
Definition: hubport.cpp:477
static const State D3FlushThenReturn
Definition: portsm.h:338
SM_RESULT EnterWithPortChange()
SM_RESULT OnD3Idle(_In_ PortEvent Event)
BOOLEAN m_D3PowerUpWarm
Definition: portsm.h:967
SM_RESULT EnterReconnectRearming()
BOOLEAN m_ReadFresh
Definition: portsm.h:960
static const State ChangeChecking30
Definition: portsm.h:285
SM_RESULT OnDrainAcking(_In_ PortEvent Event)
static const State StartReading30
Definition: portsm.h:310
SM_RESULT D3ConnectCheck(_In_ BOOLEAN AfterResume)
static const State ResumeAckingConnect
Definition: portsm.h:317
SM_RESULT DrainDone()
VOID ResetChangeAccumulator()
Definition: hubport.cpp:459
BOOLEAN StopTimer()
Definition: hubport.cpp:301
static const State StatusReporting
Definition: portsm.h:295
static const State DrainRearming
Definition: portsm.h:303
SM_RESULT EnterWakeArming()
SM_RESULT OnD3FlushThenReturn(_In_ PortEvent Event)
BOOLEAN HubArmedForWake()
Definition: fanout.cpp:1018
SM_RESULT EnterStatusFailing()
VOID ForceResetOnEnumeration()
Definition: hubport.cpp:451
static const State ReconnectRearming
Definition: portsm.h:321
VOID FixPortStateAfterPowerUp()
Definition: portxfer.cpp:692
SM_RESULT OnSuspendReading(_In_ PortEvent Event)
An error on a port that is connected but no longer enabled counts as a connect.
PSM_PENDING PendingChange()
Definition: portxfer.cpp:301
static const State SuspendIdle
Definition: portsm.h:328
static const State D3ReconnectWait
Definition: portsm.h:340
SM_RESULT FailDeviceRequest()
SM_RESULT OnStatusReading(_In_ PortEvent Event)
BOOLEAN PortPowered()
Definition: hubport.cpp:516
BOOLEAN PollResetCompletion()
Definition: hubport.cpp:545
static const State ReconnectAcking
Definition: portsm.h:320
PortEvent m_D3FlushReturn
Definition: portsm.h:958
static const State ReconnectWait
Definition: portsm.h:318
SM_RESULT EnterPowerUpRearming()
static const State D3PoweringUp
Definition: portsm.h:335
SM_RESULT OnStartReading30(_In_ PortEvent Event)
SM_RESULT ReconnectCheck()
SM_RESULT SystemResumeFailed()
VOID TakePortPowerReference()
Definition: fanout.cpp:976
SM_RESULT OnStartReading20(_In_ PortEvent Event)
SM_RESULT OnPowerOnSettling(_In_ PortEvent Event)
SM_RESULT OnChangeReading20(_In_ PortEvent Event)
SM_RESULT OnDrainChecking(_In_ PortEvent Event)
static const State D3ResumeAckWait
Definition: portsm.h:339
static const State ReconnectFlush
Definition: portsm.h:322
VOID TellDevice(_In_ PSM_DEVICE_NOTICE Notice)
Definition: hubport.cpp:309
PortEvent NextChange()
Definition: portxfer.cpp:555
SM_RESULT OnResumePowering(_In_ PortEvent Event)
SM_RESULT D3PendingDone(_In_ D3_PENDING Pending)
@ ReadPlain
Definition: portsm.h:178
@ ReadNoChange
Definition: portsm.h:179
@ ReadStartResume
Definition: portsm.h:180
static const State ResumePowering
Definition: portsm.h:314
SM_RESULT D3StopReconnectTimer(_In_ D3_PENDING Pending)
static const State StatusAcking
Definition: portsm.h:294
VOID SendGetStatus()
Definition: portxfer.cpp:152
SM_RESULT OnReconnectAcking(_In_ PortEvent Event)
static const State PowerOnSending
Definition: portsm.h:306
static const State ChangeReporting20
Definition: portsm.h:281
SM_RESULT OnResumeRereading(_In_ PortEvent Event)
SM_RESULT OnPowerUpParked(_In_ PortEvent Event)
SM_RESULT OnSuspendIdle(_In_ PortEvent Event)
VOID ReadPortBits(_Out_ PPSM_PORT_BITS Bits)
Definition: hubport.cpp:589
static const State WakeArming
Definition: portsm.h:343
SM_RESULT OnSuspendRecovery(_In_ PortEvent Event)
SM_RESULT EnterAckingChange()
static const State StartReading20
Definition: portsm.h:308
static const State ResetPollWait
Definition: portsm.h:288
D3_PENDING m_D3Pending
Definition: portsm.h:956
SM_RESULT OnDrainReading(_In_ PortEvent Event)
static const State ChangeReading20
Definition: portsm.h:279
SM_RESULT OnD3PoweredOff(_In_ PortEvent Event)
static const State StatusFailing
Definition: portsm.h:296
VOID MarkOverCurrentCause()
Definition: hubport.cpp:504
static const State SystemResumeReading
Definition: portsm.h:324
static const State SuspendRecovery
Definition: portsm.h:331
SM_RESULT EnterResetPollWait()
static const State PowerOnSettling
Definition: portsm.h:307
SM_RESULT EnterSuspendReporting()
VOID DropPortPowerReference()
Definition: fanout.cpp:982
static const State SystemResumeRereading
Definition: portsm.h:326
SM_RESULT OnResetPollChecking(_In_ PortEvent Event)
VOID StartTimer(_In_ PSM_TIMER Timer)
Definition: hubport.cpp:230
SM_RESULT EnterPowerOnSettling()
static const State ResumeReading
Definition: portsm.h:316
SM_RESULT OnD3PoweringUp(_In_ PortEvent Event)
static const State DrainAcking
Definition: portsm.h:302
SM_RESULT OnReconnectReading(_In_ PortEvent Event)
SM_RESULT ResumeStateDisabled()
VOID ResumeInterruptTransfer()
Definition: fanout.cpp:1012
SM_RESULT EnterDrainRearming()
SM_RESULT ReturnFromFrame(_In_ PortEvent Event)
Definition: portsm.cpp:289
BOOLEAN DevicePresent()
Definition: hubport.cpp:484
BOOLEAN D3ColdEnabled()
Definition: hubport.cpp:572
PortEvent LostChange()
Definition: portxfer.cpp:593
static const State D3Debouncing
Definition: portsm.h:336
SM_RESULT OnStartReadingFirst(_In_ PortEvent Event)
SM_RESULT ParkChange20(_In_ BOOLEAN ResetHub)
SM_RESULT ReconnectStatusFailed()
SM_RESULT OnD3ResumeAckWait(_In_ PortEvent Event)
static const State SuspendReading
Definition: portsm.h:329
static const State SystemReconnectWait
Definition: portsm.h:325
SM_RESULT OnPowerOnSending(_In_ PortEvent Event)
BOOLEAN m_ReconnectFlushOnStop
Definition: portsm.h:968
SM_RESULT OnD3Debouncing(_In_ PortEvent Event)
static const State D3ReconnectFlush
Definition: portsm.h:341
VOID KeepHubAwake()
Definition: portsm.cpp:257
SM_RESULT OnChangeIdle30(_In_ PortEvent Event)
SM_RESULT D3StopDebounceTimer()
static const State ChangeParked20
Definition: portsm.h:282
static const State ReconnectReading
Definition: portsm.h:319
static const State SuspendReporting
Definition: portsm.h:332
static const State ChangeIdle20
Definition: portsm.h:278
SM_RESULT OnSuspendAcking(_In_ PortEvent Event)
BOOLEAN m_Usb3
Definition: portsm.h:951
SM_RESULT EnterStatusReading()
VOID RequestHubReset()
Definition: fanout.cpp:1006
static const State ResetChangeIdle
Definition: portsm.h:286
BOOLEAN ConnectChangedOnResume()
Definition: hubport.cpp:523
static const State ResumeChangeChecking
Definition: portsm.h:291
static const State StatusReading
Definition: portsm.h:293
SM_RESULT OnSystemResumeRereading(_In_ PortEvent Event)
SM_RESULT EnterStartResumeStatusRead()
SM_RESULT OnChangeParked20(_In_ PortEvent Event)
BOOLEAN m_DrainReturnsEmpty
Definition: portsm.h:969
SM_RESULT OnChangeChecking30(_In_ PortEvent Event)
static const State DrainChecking
Definition: portsm.h:304
SM_RESULT OnResumeChangeChecking(_In_ PortEvent Event)
static SM_RESULT SmTransition(_In_ const State *Target)
Definition: smengine.h:194
static SM_RESULT SmReturn(_In_ PortEvent Ev)
Definition: smengine.h:217
static SM_RESULT SmCall(_In_ const State *Start)
Definition: smengine.h:209
static SM_RESULT SmHandled()
Definition: smengine.h:182
static SM_RESULT SmUnhandled()
Definition: smengine.h:188
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ Pending
Definition: fs_rec.h:186
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLboolean enable
Definition: glext.h:11120
static void Report(const char *msg)
Definition: glmodeswitch.c:58
#define bits
Definition: infblock.c:15
#define _In_
Definition: no_sal2.h:158
PortEvent
Definition: portsm.h:15
@ DisableSuperSpeedRequest
@ WarmResetRequest
@ HibernateRequest
@ PsmNoticeStateEnabled
Definition: portsm.h:82
@ PsmNoticeEnabledOnReconnect
Definition: portsm.h:87
@ PsmNoticeStateSuspended
Definition: portsm.h:83
@ PsmNoticeResumed
Definition: portsm.h:77
@ PsmNoticeFailed
Definition: portsm.h:74
@ PsmNoticeStateDisabled
Definition: portsm.h:81
@ PsmPendingError
Definition: portsm.h:110
@ PsmPendingChange
Definition: portsm.h:108
@ PsmTimerResetPoll
Definition: portsm.h:102
@ PsmTimerReconnect
Definition: portsm.h:99
@ PsmTimerResumeRecovery
Definition: portsm.h:97
@ PsmTimerPowerOn
Definition: portsm.h:98
@ PsmTimerDebounce
Definition: portsm.h:93
@ PsmTimerD3ColdReconnect
Definition: portsm.h:100
static const PortEvent DrainDrops[]
static const PortEvent DrainEmptyDrops20[]
static const PortEvent DrainEmptyDrops30[]
#define PSM_PASSIVE
#define PSM_YIELDS
static const PortEvent FrameRemovedOnly[]
static const PortEvent FrameGoneOnly[]
#define PSM_CRIT
#define SM_BREAK(Message)
Definition: smengine.h:18
One state. Handler gets every event the state sees.
Definition: smengine.h:93