diff -r 000000000000 -r 96e5fb8b040d userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,425 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Implements a Session of a Symbian OS server for the RUsbMassStorage API +// +// + +/** + @file + @internalTechnology +*/ + +#include + +#include "msctypes.h" +#include "shared.h" +#include "msgservice.h" +#include "cusbhostmslogicalunit.h" +#include "cusbhostmsdevice.h" +#include "msdebug.h" +#include "cusbhostmssession.h" +#include "cusbhostmsdevicethread.h" +#include "debug.h" + +/** +Constructor +*/ +TDeviceHandler::TDeviceHandler(CUsbHostMsDevice& aDevice) +: iDevice(aDevice) + { + __MSFNLOG + } + + +/** + Services messages directed to a device. Messages associated with a single + Logical Unit contained by the device are forwarded to the Logical Unit + Handler. + + @param aMessage + */ +void TDeviceHandler::HandleMessageL(const RMessage2& aMessage) + { + __MSFNLOG + TLun lun = iDevice.GetAndSetLunL(aMessage); + + switch (aMessage.Function()) + { + case EUsbHostMsSuspendLun: + iDevice.SuspendLunL(lun); + break; + case EUsbHostMsUnRegisterLun: + iDevice.RemoveLunL(lun); + break; + default: + // Try Logical Unit Handler + CUsbHostMsLogicalUnit& lu = iDevice.GetLuL(lun); + TLogicalUnitHandler luHandler(lu); + luHandler.HandleMessageL(aMessage); + break; + } + } + + +/** + Constructor + + @param aLu Reference to the logical unit object + */ +TLogicalUnitHandler::TLogicalUnitHandler(CUsbHostMsLogicalUnit& aLu) +: iLu(aLu) + { + __MSFNLOG + } + + +/** + Services messages directed to a specific Logical Unit. Unrecognized messages + will cause a PANIC. + + @param aMessage + */ +void TLogicalUnitHandler::HandleMessageL(const RMessage2& aMessage) + { + __MSFNLOG + switch (aMessage.Function()) + { + case EUsbHostMsNotifyChange: + iLu.NotifyChange(aMessage); + break; + case EUsbHostMsCancelChangeNotifier: + iLu.CancelChangeNotifierL(); + break; + case EUsbHostMsForceRemount: + iLu.ForceCompleteNotifyChangeL(); + break; + case EUsbHostMsRead: + iLu.ReadL(aMessage); + break; + case EUsbHostMsWrite: + iLu.WriteL(aMessage); + break; + case EUsbHostMsErase: + iLu.EraseL(aMessage); + break; + case EUsbHostMsCapacity: + iLu.CapsL(aMessage); + break; + default: + aMessage.Panic(KUsbHostMsSrvPncCat, EUsbMsPanicIllegalIPC); + break; + } + } + + +void CUsbHostMsDeviceThread::DoStartServerL(TAny* aPtr) + { + __MSFNSLOG + CActiveScheduler* s = new(ELeave) CActiveScheduler; + CActiveScheduler::Install(s); + + CUsbHostMsDeviceThread* iThread = (CUsbHostMsDeviceThread*)aPtr; + CActiveScheduler::Add(iThread); + + iThread->Start(); + + RThread::Rendezvous(KErrNone); + + // + // Ready to run + CActiveScheduler::Start(); + + // + // Cleanup the scheduler + delete s; + } + + +TInt CUsbHostMsDeviceThread::Entry(TAny* aPtr) + { + __MSFNSLOG + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (!cleanup) + { + return KErrNoMemory; + } + + TRAPD(error, DoStartServerL(aPtr)); + delete cleanup; + return error; + } + + +void CUsbHostMsDeviceThread::RunL() + { + __MSFNLOG + + // called on completion of MessageRequest() or Resume() + User::LeaveIfError(iStatus.Int()); + + Lock(); + if (iUsbHostMsDevice) + { + if (iUsbHostMsDevice->IsSuspended()) + { + // request resume + Unlock(); + iUsbHostMsDevice->Resume(iStatus); + SetActive(); + return; + } + } + + // process message queue + RMessage2 msg = iRMessage2[iDequeueIndex]; + + iDequeueIndex++; + + if(iDequeueIndex >= KMaxNumMessage) + iDequeueIndex = 0; + if(iQueueFull) + iQueueFull = EFalse; + + HandleMessage(msg); + + if ((iQueueIndex != iDequeueIndex) || iQueueFull) + { + // self completion + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + SetActive(); + } + else + { + iUsbHostMsSession.MessageRequest(iStatus); + SetActive(); + } + Unlock(); + } + + +void CUsbHostMsDeviceThread::DoCancel() + { + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrCancel); + } + + +TInt CUsbHostMsDeviceThread::RunError(TInt aError) +{ + __HOSTPRINT1(_L(">> HOST RunError returning %d"), aError); + return KErrNone; +} + + +TInt CUsbHostMsDeviceThread::QueueMsg(const RMessage2& aMsg) + { + __MSFNLOG + + if (iQueueFull) + { + return KErrOverflow; + } + + Lock(); + + iRMessage2[iQueueIndex] = aMsg; + iQueueIndex++; + + if (iQueueIndex >= KMaxNumMessage) + { + iQueueIndex = 0; + } + + if (iQueueIndex == iDequeueIndex) + { + iQueueFull = ETrue; + } + Unlock(); + return KErrNone; + } + + +CUsbHostMsDeviceThread::CUsbHostMsDeviceThread(CUsbHostMsSession& aUsbHostMsSession, TUint aToken) +: CActive(EPriorityStandard), + iUsbHostMsSession(aUsbHostMsSession), + iQueueFull(EFalse) + { + __MSFNLOG + TBuf<30> nameBuf; + nameBuf.Format(_L("Host Ms ThreadMutex%d"), aToken); + iMutex.CreateGlobal(nameBuf,EOwnerProcess); + } + +CUsbHostMsDeviceThread::~CUsbHostMsDeviceThread() + { + __MSFNLOG + Cancel(); + iMutex.Close(); + } + +CUsbHostMsDeviceThread* CUsbHostMsDeviceThread::NewL(CUsbHostMsSession& aUsbHostMsSession, TUint aToken) + { + __MSFNSLOG + CUsbHostMsDeviceThread* r = new (ELeave) CUsbHostMsDeviceThread(aUsbHostMsSession, aToken); + return r; + } + + +void CUsbHostMsDeviceThread::Start() + { + iUsbHostMsSession.MessageRequest(iStatus); + SetActive(); + } + + +/** + Handles the request (in the form of a message) received from the client +@param aMessage The received message + */ +void CUsbHostMsDeviceThread::HandleMessage(const RMessage2& aMessage) + { + __MSFNLOG + TInt ret = KErrNotReady; + __HOSTPRINT2(_L(">> HOST DispatchMessageL Function=%d %d"), aMessage.Function(), aMessage.Int3()); + switch (aMessage.Function()) + { + case EUsbHostMsRegisterInterface: + TRAP(ret, RegisterInterfaceL(aMessage)); + break; + case EUsbHostMsInitialiseInterface: + TRAP(ret, InitialiseInterfaceL(aMessage)); + // CUsbInterfaceHandler::GetMaxLun() completes asynchronously + if (ret) + { + // Error condition needs to be completed + break; + } + return; + case EUsbHostMsUnRegisterInterface: + TRAP(ret, UnRegisterInterfaceL(aMessage)); + break; + case EUsbHostMsRegisterLun: + TRAP(ret, RegisterLogicalUnitL(aMessage)); + break; + case EUsbHostMsGetNumLun: + TRAP(ret, GetNumLunL(aMessage)); + break; + case EUsbHostMsShutdown: + ret = Shutdown(); + break; + default: + // Try Device Handler and Logical Unit Handler + __ASSERT_DEBUG(iUsbHostMsDevice, User::Invariant()); + TDeviceHandler deviceHandler(*iUsbHostMsDevice); + TRAP(ret, deviceHandler.HandleMessageL(aMessage)); + break; + } + __HOSTPRINT1(_L(">> HOST returning %d"), ret); + + if (aMessage.Function() != EUsbHostMsNotifyChange) + { + aMessage.Complete(ret); + } + } + + +/** +Client request to shut down the server + +return KErrNone +*/ +TInt CUsbHostMsDeviceThread::Shutdown() + { + __MSFNLOG + CActiveScheduler::Stop(); + return KErrNone; + } + +void CUsbHostMsDeviceThread::GetNumLunL(const RMessage2& aMessage) + { + __MSFNLOG + if (!iUsbHostMsDevice) + { + User::Leave(KErrNotReady); + } + + TUint32 maxLun = iUsbHostMsDevice->GetMaxLun() + 1; + TPtrC8 pLun((TUint8*)&maxLun,sizeof(TUint32)); + aMessage.WriteL(0,pLun); + } + + +void CUsbHostMsDeviceThread::RegisterInterfaceL(const RMessage2& aMessage) + { + __MSFNLOG + + THostMassStorageConfig msDeviceConfig; + TPtr8 ptr((TUint8*)&msDeviceConfig,sizeof(THostMassStorageConfig)); + aMessage.ReadL(0, ptr); + + __HOSTPRINT1(_L("RegisterInterfaceL Token=%d "), msDeviceConfig.iInterfaceToken); + + iUsbHostMsDevice = CUsbHostMsDevice::NewL(msDeviceConfig); + } + + +void CUsbHostMsDeviceThread::InitialiseInterfaceL(const RMessage2& aMessage) + { + __MSFNLOG + if (!iUsbHostMsDevice) + { + User::Leave(KErrNotReady); + } + + TRAPD(err, iUsbHostMsDevice->InitialiseL(aMessage)); + if (err != KErrNone) + { + delete iUsbHostMsDevice; + iUsbHostMsDevice = NULL; + User::Leave(err); + } + } + + +void CUsbHostMsDeviceThread::UnRegisterInterfaceL(const RMessage2& aMessage) + { + __MSFNLOG + if (!iUsbHostMsDevice) + { + User::Leave(KErrNotReady); + } + + TRAPD(err, iUsbHostMsDevice->UnInitialiseL()); + delete iUsbHostMsDevice; + iUsbHostMsDevice = NULL; + User::LeaveIfError(err); + } + + +void CUsbHostMsDeviceThread::RegisterLogicalUnitL(const RMessage2& aMessage) + { + if (!iUsbHostMsDevice) + { + User::Leave(KErrNotReady); + } + + TUint32 iLunId = aMessage.Int0() + 1; // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1 + TPtrC8 pLun((TUint8*)&iLunId, sizeof(TUint32)); + aMessage.WriteL(3, pLun); + iLunId -= 1; // We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT + iUsbHostMsDevice->AddLunL(iLunId); + iUsbHostMsDevice->InitLunL(iLunId); + } +