os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/protocol/cmassstoragefsm.cpp
First public contribution.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
23 #include "usbmshostpanic.h"
28 #include "mprotocol.h"
29 #include "mblocktransferprotocol.h"
30 #include "tspcclientinterface.h"
31 #include "cscsiprotocol.h"
32 #include "cmassstoragefsm.h"
38 @param aScsiProtocol A reference to CScsiProtocol
40 TMassStorage::TMassStorage(CScsiProtocol& aScsiProtocol)
41 : iScsiProtocol(aScsiProtocol)
48 Clear StatusCheck flag. Periodic status checking is used for removable media.
50 void CMassStorageFsm::ClearStatusCheck()
53 iStatusCheck = EFalse;
58 Set StatusCheck flag. Periodic status checking is used for removable media.
60 void CMassStorageFsm::SetStatusCheck()
68 Get the boolean state of StatusCheck flag.
70 @return TBool ETrue if StatusCheck flag is set
72 TBool CMassStorageFsm::IsStatusCheck() const
80 Device supports SCSI BLOCK COMMANDS.
82 @return TBool Returns ETrue if the SBC interface is initialised
84 TBool TMassStorage::IsSbcSet() const
87 return iScsiProtocol.MsIsSbcSet();
91 Device is removable media
93 @return TBool Returns ETrue if removable
95 TBool TMassStorage::IsRemovableMedia() const
98 return iScsiProtocol.MsIsRemovableMedia();
102 Retrieve the sense info returned by a call to SenseL
104 @return const TSenseInfo& Returns the SCSI SENSE info
106 const TSenseInfo& TMassStorage::MsSenseInfo() const
109 return iScsiProtocol.MsSenseInfo();
114 TMassStorage::TEvent TMassStorage::InquiryL()
117 TEvent event = EEvCommandFailed;
119 switch (iScsiProtocol.MsInquiryL())
122 event = EEvCommandPassed;
124 case KErrCommandFailed:
125 event = EEvCommandFailed;
127 case KErrNotSupported:
128 __SCSIPRINT(_L("INQUIRY Command returned NOT SUPPORTED"));
129 User::Leave(KErrNotSupported);
132 User::Leave(KErrUnknown);
140 TMassStorage::TEvent TMassStorage::SenseL()
143 TEvent event = EEvCommandPassed;
144 switch (iScsiProtocol.MsRequestSenseL())
148 case KErrCommandFailed:
149 __SCSIPRINT(_L("REQUEST SENSE Command Failed"));
150 User::Leave(KErrNotSupported);
153 User::Leave(KErrUnknown);
161 TMassStorage::TEvent TMassStorage::TestUnitReadyL()
164 // KErrCommandFailed indictates that device is NOT READY
165 TInt err = iScsiProtocol.MsTestUnitReadyL();
166 return (err == KErrNone) ? EEvCommandPassed : EEvCommandFailed;
171 TMassStorage::TEvent TMassStorage::StartStopUnitL(TBool aStart)
174 TInt err = iScsiProtocol.MsStartStopUnitL(aStart);
175 return (err == KErrNone) ? EEvCommandPassed : EEvCommandFailed;
180 TMassStorage::TEvent TMassStorage::PreventAllowMediumRemovalL(TBool aPrevent)
183 // KErrCommandFailed indictates that device is NOT READY
184 TInt err = iScsiProtocol.MsPreventAllowMediaRemovalL(aPrevent);
185 return (err == KErrNone) ? EEvCommandPassed : EEvCommandFailed;
190 TMassStorage::TEvent TMassStorage::ReadCapacityL()
193 TInt err = iScsiProtocol.MsReadCapacityL();
194 return ErrToEvent(err);
199 TMassStorage::TEvent TMassStorage::ModeSense10L()
202 TInt err = iScsiProtocol.MsModeSense10L();
203 return ErrToEvent(err);
208 TMassStorage::TEvent TMassStorage::ModeSense6L()
211 TInt err = iScsiProtocol.MsModeSense6L();
212 return ErrToEvent(err);
217 Creates and returns a pointer to CMassStorageFsm.
219 @param aScsiProtocol A reference to the protocol providing the interface to the
222 @return CMassStorageFsm* A pointer to the newly created object
224 CMassStorageFsm* CMassStorageFsm::NewL(CScsiProtocol& aScsiProtocol)
227 CMassStorageFsm* r = new (ELeave) CMassStorageFsm(aScsiProtocol);
229 CleanupStack::PushL(r);
235 void CMassStorageFsm::ConstructL()
240 iStateTable[i++] = new (ELeave) TInquiryState;
241 // EInquirySenseState,
242 iStateTable[i++] = new (ELeave) TInquirySenseState;
244 iStateTable[i++] = new (ELeave) TNotReadyState;
245 // ENotReadySenseState,
246 iStateTable[i++] = new (ELeave) TNotReadySenseState;
248 iStateTable[i++] = new (ELeave) TStartUnitState;
249 //EStartUnitSenseState,
250 iStateTable[i++] = new (ELeave) TStartUnitSenseState;
251 //EPreventAllowMediumRemovalState,
252 iStateTable[i++] = new (ELeave) TPreventMediumRemovalState;
253 //EPreventAllowMediumRemovalSenseState,
254 iStateTable[i++] = new (ELeave) TPreventMediumRemovalSenseState;
255 //EReadCapacity10State,
256 iStateTable[i++] = new (ELeave) TReadCapacity10State;
258 iStateTable[i++] = new (ELeave) TModeSense10State;
259 //EModeSense10SenseState,
260 iStateTable[i++] = new (ELeave) TModeSense10SenseState;
262 iStateTable[i++] = new (ELeave) TModeSense6State;
263 //EModeSense6SenseState,
264 iStateTable[i++] = new (ELeave) TModeSense6SenseState;
266 iStateTable[i++] = new (ELeave) TConnectedState;
268 iStateTable[i++] = new (ELeave) TStatusCheckState;
269 //EAllowMediumRemovalState,
270 iStateTable[i++] = new (ELeave) TAllowMediumRemovalState;
272 iStateTable[i++] = new (ELeave) TStopUnitState;
274 iStateTable[i++] = new (ELeave) TSenseState;
277 // verify state table
278 for (TInt i = 0; i < iStateTable.Count(), i++)
280 __ASSERT_DEBUG(i == iStateTable[i].iStateId, User::Invariant());
284 SetState(TMassStorageState::EInquiryState);
288 CMassStorageFsm::CMassStorageFsm(CScsiProtocol& aScsiProtocol)
289 : TMassStorage(aScsiProtocol),
290 iStartStopUnitRequired(EFalse)
295 CMassStorageFsm::~CMassStorageFsm()
299 for (TInt i = 0; i < iStateTable.Count(); i++)
301 delete iStateTable[i];
306 TMassStorage::TEvent CMassStorageFsm::EntryL()
310 return iState->EntryL(*this);
315 Run FSM to connect device.
317 @return TInt KErrCompletion if successful otherwise KErrNotSupported
319 TInt CMassStorageFsm::ConnectLogicalUnitL()
325 err = ProcessStateL();
334 Run FSM to disconnect the device.
336 @return TInt KErrCompletion if successful otherwise KErrNotSupported
338 TInt CMassStorageFsm::DisconnectLogicalUnitL()
344 TInt err = ProcessStateL();
353 Return current FSM state.
355 @return TBool ETrue if FSM state is Connected State
357 TBool CMassStorageFsm::IsConnected() const
360 return iState->iStateId == TMassStorageState::EConnectedState ? ETrue : EFalse;
364 TInt CMassStorageFsm::ProcessStateL()
367 TMassStorage::TEvent event = TMassStorage::EEvCommandFailed;
368 TRAPD(err, event = EntryL());
369 if (err == KErrNotSupported)
371 return KErrNotSupported;
373 User::LeaveIfError(err);
375 __HOSTPRINT1(_L("FSM event=%d"), event);
378 case TMassStorage::EEvCommandPassed:
379 err = ScsiCommandPassed();
381 case TMassStorage::EEvCommandFailed:
382 err = ScsiCommandFailed();
384 case TMassStorage::EEvCommandError:
385 err = ScsiCommandError();
388 User::Panic(KUsbMsHostPanicCat, EMsFsmEvent);
392 __HOSTPRINT1(_L("FSM ProcessState completed=%d"), err);
397 TInt CMassStorageFsm::ScsiCommandPassed()
400 return iState->ScsiCommandPassed(*this);
404 TInt CMassStorageFsm::ScsiCommandFailed()
407 return iState->ScsiCommandFailed(*this);
411 TInt CMassStorageFsm::ScsiCommandError()
414 return iState->ScsiCommandError(*this);
421 @param aStateId The state id of the state implementation
423 TMassStorageState::TMassStorageState(TStateId aStateId)
431 Default state does nothing. Used by states where the stalled event is not
438 TInt TMassStorageState::ScsiCommandError(CMassStorageFsm& /* aFsm */)
444 TInt TMassStorageState::SenseError(CMassStorageFsm& aFsm)
448 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
450 if (senseInfo.iSenseCode == TSenseInfo::EUnitAttention)
452 aFsm.SetState(TMassStorageState::EInquiryState);
456 aFsm.SetState(TMassStorageState::ENotReadyState);
457 ret = KErrCompletion;
466 TInquiryState::TInquiryState()
467 : TMassStorageState(EInquiryState)
473 TMassStorage::TEvent TInquiryState::EntryL(CMassStorageFsm& aFsm)
476 return aFsm.InquiryL();
480 TInt TInquiryState::ScsiCommandPassed(CMassStorageFsm& aFsm)
483 aFsm.SetState(ENotReadyState);
488 TInt TInquiryState::ScsiCommandFailed(CMassStorageFsm& aFsm)
491 aFsm.SetState(EInquirySenseState);
499 TInquirySenseState::TInquirySenseState()
500 : TMassStorageState(EInquirySenseState)
506 TMassStorage::TEvent TInquirySenseState::EntryL(CMassStorageFsm& aFsm)
509 return aFsm.SenseL();
513 TInt TInquirySenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
517 aFsm.SetState(TMassStorageState::EInquiryState);
518 return KErrCompletion;
522 TInt TInquirySenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
525 aFsm.SetState(TMassStorageState::EInquiryState);
526 return KErrCompletion;
533 TNotReadyState::TNotReadyState()
534 : TMassStorageState(ENotReadyState)
540 TMassStorage::TEvent TNotReadyState::EntryL(CMassStorageFsm& aFsm)
543 return aFsm.TestUnitReadyL();
547 TInt TNotReadyState::ScsiCommandPassed(CMassStorageFsm& aFsm)
552 if (aFsm.IsRemovableMedia())
553 aFsm.SetState(TMassStorageState::EPreventRemovalState);
555 aFsm.SetState(TMassStorageState::EReadCapacityState);
558 aFsm.SetState(TMassStorageState::EInquiryState);
563 TInt TNotReadyState::ScsiCommandFailed(CMassStorageFsm& aFsm)
566 aFsm.SetState(TMassStorageState::ENotReadySenseState);
574 TNotReadySenseState::TNotReadySenseState()
575 : TMassStorageState(ENotReadySenseState)
581 TMassStorage::TEvent TNotReadySenseState::EntryL(CMassStorageFsm& aFsm)
584 return aFsm.SenseL();
588 TInt TNotReadySenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
591 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
594 if (senseInfo.iSenseCode == TSenseInfo::ENotReady &&
595 senseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady &&
596 senseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired)
598 aFsm.SetStartStopUnitRequired(ETrue);
599 aFsm.SetState(TMassStorageState::EStartUnitState);
603 ret = TMassStorageState::SenseError(aFsm);
610 TInt TNotReadySenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
613 return TMassStorageState::SenseError(aFsm);
620 TStartUnitState::TStartUnitState()
621 : TMassStorageState(EPreventRemovalState)
627 TMassStorage::TEvent TStartUnitState::EntryL(CMassStorageFsm& aFsm)
630 return aFsm.StartStopUnitL(ETrue);
634 TInt TStartUnitState::ScsiCommandPassed(CMassStorageFsm& aFsm)
637 if (aFsm.IsRemovableMedia())
638 aFsm.SetState(TMassStorageState::EPreventRemovalState);
640 aFsm.SetState(TMassStorageState::EReadCapacityState);
645 TInt TStartUnitState::ScsiCommandFailed(CMassStorageFsm& aFsm)
648 aFsm.SetState(TMassStorageState::EPreventRemovalSenseState);
655 TStartUnitSenseState::TStartUnitSenseState()
656 : TMassStorageState(EPreventRemovalSenseState)
662 TMassStorage::TEvent TStartUnitSenseState::EntryL(CMassStorageFsm& aFsm)
665 return aFsm.SenseL();
669 TInt TStartUnitSenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
672 if (aFsm.IsRemovableMedia())
673 aFsm.SetState(TMassStorageState::EPreventRemovalState);
675 aFsm.SetState(TMassStorageState::EReadCapacityState);
681 TInt TStartUnitSenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
684 TInt ret = KErrCompletion;
685 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
687 aFsm.SetState(TMassStorageState::EInquiryState);
688 if (senseInfo.iSenseCode == TSenseInfo::EIllegalRequest)
690 aFsm.SetState(TMassStorageState::EReadCapacityState);
695 ret = TMassStorageState::SenseError(aFsm);
705 TPreventMediumRemovalState::TPreventMediumRemovalState()
706 : TMassStorageState(EPreventRemovalState)
712 TMassStorage::TEvent TPreventMediumRemovalState::EntryL(CMassStorageFsm& aFsm)
715 return aFsm.PreventAllowMediumRemovalL(ETrue);
719 TInt TPreventMediumRemovalState::ScsiCommandPassed(CMassStorageFsm& aFsm)
722 aFsm.SetState(TMassStorageState::EReadCapacityState);
727 TInt TPreventMediumRemovalState::ScsiCommandFailed(CMassStorageFsm& aFsm)
730 aFsm.SetState(TMassStorageState::EPreventRemovalSenseState);
737 TPreventMediumRemovalSenseState::TPreventMediumRemovalSenseState()
738 : TMassStorageState(EPreventRemovalSenseState)
744 TMassStorage::TEvent TPreventMediumRemovalSenseState::EntryL(CMassStorageFsm& aFsm)
747 return aFsm.SenseL();
751 TInt TPreventMediumRemovalSenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
754 aFsm.SetState(TMassStorageState::EReadCapacityState);
761 TInt TPreventMediumRemovalSenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
764 TInt ret = KErrCompletion;
765 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
767 if (senseInfo.iSenseCode == TSenseInfo::EIllegalRequest)
769 aFsm.SetState(TMassStorageState::EReadCapacityState);
774 ret = TMassStorageState::SenseError(aFsm);
783 TReadCapacity10State::TReadCapacity10State()
784 : TMassStorageState(EReadCapacityState)
790 TMassStorage::TEvent TReadCapacity10State::EntryL(CMassStorageFsm& aFsm)
793 return aFsm.ReadCapacityL();
797 TInt TReadCapacity10State::ScsiCommandPassed(CMassStorageFsm& aFsm)
800 aFsm.SetState(EModeSense10State);
805 TInt TReadCapacity10State::ScsiCommandFailed(CMassStorageFsm& aFsm)
808 aFsm.SetState(TMassStorageState::ESenseState);
809 return KErrCompletion;
813 TInt TReadCapacity10State::ScsiCommandError(CMassStorageFsm& aFsm)
816 aFsm.SetState(TMassStorageState::ENotReadyState);
817 return KErrCompletion;
824 TModeSense10State::TModeSense10State()
825 : TMassStorageState(EModeSense10State)
831 TMassStorage::TEvent TModeSense10State::EntryL(CMassStorageFsm& aFsm)
834 return aFsm.ModeSense10L();
838 TInt TModeSense10State::ScsiCommandPassed(CMassStorageFsm& aFsm)
841 aFsm.SetState(EConnectedState);
842 return KErrCompletion;
846 TInt TModeSense10State::ScsiCommandFailed(CMassStorageFsm& aFsm)
849 aFsm.SetState(EModeSense10SenseState);
854 TInt TModeSense10State::ScsiCommandError(CMassStorageFsm& aFsm)
857 aFsm.SetState(EModeSense6State);
864 TModeSense10SenseState::TModeSense10SenseState()
865 : TMassStorageState(EModeSense10SenseState)
871 TMassStorage::TEvent TModeSense10SenseState::EntryL(CMassStorageFsm& aFsm)
874 return aFsm.SenseL();
878 TInt TModeSense10SenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
881 TInt ret = KErrCompletion;
882 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
884 aFsm.SetState(TMassStorageState::EInquiryState);
885 if (senseInfo.iSenseCode == TSenseInfo::EIllegalRequest)
887 aFsm.SetState(TMassStorageState::EModeSense6State);
892 ret = TMassStorageState::SenseError(aFsm);
898 TInt TModeSense10SenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
901 aFsm.SetState(EInquirySenseState);
902 return KErrCompletion;
908 TModeSense6State::TModeSense6State()
909 : TMassStorageState(EModeSense6State)
915 TMassStorage::TEvent TModeSense6State::EntryL(CMassStorageFsm& aFsm)
918 return aFsm.ModeSense6L();
922 TInt TModeSense6State::ScsiCommandPassed(CMassStorageFsm& aFsm)
925 aFsm.SetState(EConnectedState);
926 return KErrCompletion;
930 TInt TModeSense6State::ScsiCommandFailed(CMassStorageFsm& aFsm)
933 aFsm.SetState(EModeSense6SenseState);
938 TInt TModeSense6State::ScsiCommandError(CMassStorageFsm& aFsm)
941 // If device responds with protocol error, ignore the error and assume the
942 // device is not write protected
943 aFsm.SetState(EConnectedState);
944 return KErrCompletion;
951 TModeSense6SenseState::TModeSense6SenseState()
952 : TMassStorageState(EModeSense6SenseState)
958 TMassStorage::TEvent TModeSense6SenseState::EntryL(CMassStorageFsm& aFsm)
961 return aFsm.SenseL();
965 TInt TModeSense6SenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
968 TInt ret = KErrCompletion;
969 const TSenseInfo& senseInfo = aFsm.MsSenseInfo();
971 aFsm.SetState(TMassStorageState::EInquiryState);
972 if (senseInfo.iSenseCode == TSenseInfo::EIllegalRequest)
974 aFsm.SetState(TMassStorageState::EConnectedState);
978 ret = TMassStorageState::SenseError(aFsm);
984 TInt TModeSense6SenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
987 aFsm.SetState(EInquirySenseState);
988 return KErrCompletion;
996 TConnectedState::TConnectedState()
997 : TMassStorageState(EConnectedState)
1003 TMassStorage::TEvent TConnectedState::EntryL(CMassStorageFsm& /* aFsm */)
1006 return TMassStorage::EEvCommandPassed;
1010 TInt TConnectedState::ScsiCommandPassed(CMassStorageFsm& aFsm)
1013 TInt ret = KErrNone;
1015 if (aFsm.IsRemovableMedia())
1017 if(aFsm.IsStatusCheck())
1019 aFsm.SetState(TMassStorageState::EStatusCheckState);
1023 aFsm.SetState(TMassStorageState::EAllowRemovalState);
1026 else if (aFsm.StartStopUnitRequired())
1028 aFsm.SetState(TMassStorageState::EStopUnitState);
1032 aFsm.SetState(TMassStorageState::ENotReadyState);
1033 ret = KErrCompletion;
1039 TInt TConnectedState::ScsiCommandFailed(CMassStorageFsm& aFsm)
1042 aFsm.SetState(TMassStorageState::EInquiryState);
1043 return KErrCompletion;
1050 TStatusCheckState::TStatusCheckState()
1051 : TMassStorageState(EStatusCheckState)
1057 TMassStorage::TEvent TStatusCheckState::EntryL(CMassStorageFsm& aFsm)
1060 return aFsm.TestUnitReadyL();
1064 TInt TStatusCheckState::ScsiCommandPassed(CMassStorageFsm& aFsm)
1067 aFsm.SetState(EConnectedState);
1068 return KErrCompletion;
1072 TInt TStatusCheckState::ScsiCommandFailed(CMassStorageFsm& aFsm)
1075 aFsm.SetState(ESenseState);
1083 TAllowMediumRemovalState::TAllowMediumRemovalState()
1084 : TMassStorageState(EAllowRemovalState)
1090 TMassStorage::TEvent TAllowMediumRemovalState::EntryL(CMassStorageFsm& aFsm)
1093 return aFsm.PreventAllowMediumRemovalL(EFalse);
1097 TInt TAllowMediumRemovalState::ScsiCommandPassed(CMassStorageFsm& aFsm)
1100 TInt ret = KErrNone;
1101 if (aFsm.StartStopUnitRequired())
1103 aFsm.SetState(TMassStorageState::EStopUnitState);
1107 aFsm.SetState(ENotReadyState);
1108 ret = KErrCompletion;
1114 TInt TAllowMediumRemovalState::ScsiCommandFailed(CMassStorageFsm& aFsm)
1117 aFsm.SetState(TMassStorageState::EInquiryState);
1118 return KErrCompletion;
1125 TStopUnitState::TStopUnitState()
1126 : TMassStorageState(EStopUnitState)
1132 TMassStorage::TEvent TStopUnitState::EntryL(CMassStorageFsm& aFsm)
1135 return aFsm.StartStopUnitL(EFalse);
1139 TInt TStopUnitState::ScsiCommandPassed(CMassStorageFsm& aFsm)
1142 aFsm.SetState(ENotReadyState);
1143 return KErrCompletion;
1147 TInt TStopUnitState::ScsiCommandFailed(CMassStorageFsm& aFsm)
1150 aFsm.SetState(TMassStorageState::EInquiryState);
1151 return KErrCompletion;
1158 TSenseState::TSenseState()
1159 : TMassStorageState(EConnectedState)
1165 TMassStorage::TEvent TSenseState::EntryL(CMassStorageFsm& aFsm)
1168 return aFsm.SenseL();
1172 TInt TSenseState::ScsiCommandPassed(CMassStorageFsm& aFsm)
1175 aFsm.SetState(ENotReadyState);
1176 return KErrCompletion;
1180 TInt TSenseState::ScsiCommandFailed(CMassStorageFsm& aFsm)
1183 // This event should not happen
1184 aFsm.SetState(EInquiryState);
1185 return KErrCompletion;