os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.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.
14 // Implements a Session of a Symbian OS server for the RUsbMassStorage API
27 #include "msgservice.h"
28 #include "cusbhostmslogicalunit.h"
29 #include "cusbhostmsdevice.h"
31 #include "cusbhostmssession.h"
32 #include "cusbhostmsdevicethread.h"
38 TDeviceHandler::TDeviceHandler(CUsbHostMsDevice& aDevice)
46 Services messages directed to a device. Messages associated with a single
47 Logical Unit contained by the device are forwarded to the Logical Unit
52 void TDeviceHandler::HandleMessageL(const RMessage2& aMessage)
55 TLun lun = iDevice.GetAndSetLunL(aMessage);
57 switch (aMessage.Function())
59 case EUsbHostMsSuspendLun:
60 iDevice.SuspendLunL(lun);
62 case EUsbHostMsUnRegisterLun:
63 iDevice.RemoveLunL(lun);
66 // Try Logical Unit Handler
67 CUsbHostMsLogicalUnit& lu = iDevice.GetLuL(lun);
68 TLogicalUnitHandler luHandler(lu);
69 luHandler.HandleMessageL(aMessage);
78 @param aLu Reference to the logical unit object
80 TLogicalUnitHandler::TLogicalUnitHandler(CUsbHostMsLogicalUnit& aLu)
88 Services messages directed to a specific Logical Unit. Unrecognized messages
93 void TLogicalUnitHandler::HandleMessageL(const RMessage2& aMessage)
96 switch (aMessage.Function())
98 case EUsbHostMsNotifyChange:
99 iLu.NotifyChange(aMessage);
101 case EUsbHostMsCancelChangeNotifier:
102 iLu.CancelChangeNotifierL();
104 case EUsbHostMsForceRemount:
105 iLu.ForceCompleteNotifyChangeL();
110 case EUsbHostMsWrite:
111 iLu.WriteL(aMessage);
113 case EUsbHostMsErase:
114 iLu.EraseL(aMessage);
116 case EUsbHostMsCapacity:
120 aMessage.Panic(KUsbHostMsSrvPncCat, EUsbMsPanicIllegalIPC);
126 void CUsbHostMsDeviceThread::DoStartServerL(TAny* aPtr)
129 CActiveScheduler* s = new(ELeave) CActiveScheduler;
130 CActiveScheduler::Install(s);
132 CUsbHostMsDeviceThread* iThread = (CUsbHostMsDeviceThread*)aPtr;
133 CActiveScheduler::Add(iThread);
137 RThread::Rendezvous(KErrNone);
141 CActiveScheduler::Start();
144 // Cleanup the scheduler
149 TInt CUsbHostMsDeviceThread::Entry(TAny* aPtr)
152 CTrapCleanup* cleanup = CTrapCleanup::New();
158 TRAPD(error, DoStartServerL(aPtr));
164 void CUsbHostMsDeviceThread::RunL()
168 // called on completion of MessageRequest() or Resume()
169 User::LeaveIfError(iStatus.Int());
172 if (iUsbHostMsDevice)
174 if (iUsbHostMsDevice->IsSuspended())
178 iUsbHostMsDevice->Resume(iStatus);
184 // process message queue
185 RMessage2 msg = iRMessage2[iDequeueIndex];
189 if(iDequeueIndex >= KMaxNumMessage)
196 if ((iQueueIndex != iDequeueIndex) || iQueueFull)
199 TRequestStatus* status = &iStatus;
200 User::RequestComplete(status, KErrNone);
205 iUsbHostMsSession.MessageRequest(iStatus);
212 void CUsbHostMsDeviceThread::DoCancel()
214 TRequestStatus* status = &iStatus;
215 User::RequestComplete(status, KErrCancel);
219 TInt CUsbHostMsDeviceThread::RunError(TInt aError)
221 __HOSTPRINT1(_L(">> HOST RunError returning %d"), aError);
226 TInt CUsbHostMsDeviceThread::QueueMsg(const RMessage2& aMsg)
237 iRMessage2[iQueueIndex] = aMsg;
240 if (iQueueIndex >= KMaxNumMessage)
245 if (iQueueIndex == iDequeueIndex)
254 CUsbHostMsDeviceThread::CUsbHostMsDeviceThread(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
255 : CActive(EPriorityStandard),
256 iUsbHostMsSession(aUsbHostMsSession),
261 nameBuf.Format(_L("Host Ms ThreadMutex%8x"), aToken);
262 iMutex.CreateGlobal(nameBuf,EOwnerProcess);
265 CUsbHostMsDeviceThread::~CUsbHostMsDeviceThread()
272 CUsbHostMsDeviceThread* CUsbHostMsDeviceThread::NewL(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
275 CUsbHostMsDeviceThread* r = new (ELeave) CUsbHostMsDeviceThread(aUsbHostMsSession, aToken);
280 void CUsbHostMsDeviceThread::Start()
282 iUsbHostMsSession.MessageRequest(iStatus);
288 Handles the request (in the form of a message) received from the client
289 @param aMessage The received message
291 void CUsbHostMsDeviceThread::HandleMessage(const RMessage2& aMessage)
294 TInt ret = KErrNotReady;
295 __HOSTPRINT2(_L(">> HOST DispatchMessageL Function=%d %d"), aMessage.Function(), aMessage.Int3());
296 switch (aMessage.Function())
298 case EUsbHostMsRegisterInterface:
299 TRAP(ret, RegisterInterfaceL(aMessage));
301 case EUsbHostMsInitialiseInterface:
302 TRAP(ret, InitialiseInterfaceL(aMessage));
303 // CUsbInterfaceHandler::GetMaxLun() completes asynchronously
306 // Error condition needs to be completed
310 case EUsbHostMsUnRegisterInterface:
311 TRAP(ret, UnRegisterInterfaceL(aMessage));
313 case EUsbHostMsRegisterLun:
314 TRAP(ret, RegisterLogicalUnitL(aMessage));
316 case EUsbHostMsGetNumLun:
317 TRAP(ret, GetNumLunL(aMessage));
319 case EUsbHostMsShutdown:
323 // Try Device Handler and Logical Unit Handler
324 __ASSERT_DEBUG(iUsbHostMsDevice, User::Invariant());
325 TDeviceHandler deviceHandler(*iUsbHostMsDevice);
326 TRAP(ret, deviceHandler.HandleMessageL(aMessage));
329 __HOSTPRINT1(_L(">> HOST returning %d"), ret);
331 if (aMessage.Function() != EUsbHostMsNotifyChange)
333 aMessage.Complete(ret);
339 Client request to shut down the server
343 TInt CUsbHostMsDeviceThread::Shutdown()
346 CActiveScheduler::Stop();
350 void CUsbHostMsDeviceThread::GetNumLunL(const RMessage2& aMessage)
353 if (!iUsbHostMsDevice)
355 User::Leave(KErrNotReady);
358 TUint32 maxLun = iUsbHostMsDevice->GetMaxLun() + 1;
359 TPtrC8 pLun((TUint8*)&maxLun,sizeof(TUint32));
360 aMessage.WriteL(0,pLun);
364 void CUsbHostMsDeviceThread::RegisterInterfaceL(const RMessage2& aMessage)
368 THostMassStorageConfig msDeviceConfig;
369 TPtr8 ptr((TUint8*)&msDeviceConfig,sizeof(THostMassStorageConfig));
370 aMessage.ReadL(0, ptr);
372 __HOSTPRINT1(_L("RegisterInterfaceL Token=%d "), msDeviceConfig.iInterfaceToken);
374 iUsbHostMsDevice = CUsbHostMsDevice::NewL(msDeviceConfig);
378 void CUsbHostMsDeviceThread::InitialiseInterfaceL(const RMessage2& aMessage)
381 if (!iUsbHostMsDevice)
383 User::Leave(KErrNotReady);
386 TRAPD(err, iUsbHostMsDevice->InitialiseL(aMessage));
389 delete iUsbHostMsDevice;
390 iUsbHostMsDevice = NULL;
396 void CUsbHostMsDeviceThread::UnRegisterInterfaceL(const RMessage2& aMessage)
399 if (!iUsbHostMsDevice)
401 User::Leave(KErrNotReady);
404 TRAPD(err, iUsbHostMsDevice->UnInitialiseL());
405 delete iUsbHostMsDevice;
406 iUsbHostMsDevice = NULL;
407 User::LeaveIfError(err);
411 void CUsbHostMsDeviceThread::RegisterLogicalUnitL(const RMessage2& aMessage)
413 if (!iUsbHostMsDevice)
415 User::Leave(KErrNotReady);
418 TUint32 iLunId = aMessage.Int0() + 1; // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
419 TPtrC8 pLun((TUint8*)&iLunId, sizeof(TUint32));
420 aMessage.WriteL(3, pLun);
421 iLunId -= 1; // We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT
422 iUsbHostMsDevice->AddLunL(iLunId);
423 iUsbHostMsDevice->InitLunL(iLunId);