os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,425 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Implements a Session of a Symbian OS server for the RUsbMassStorage API
1.18 +//
1.19 +//
1.20 +
1.21 +/**
1.22 + @file
1.23 + @internalTechnology
1.24 +*/
1.25 +
1.26 +#include <e32base.h>
1.27 +
1.28 +#include "msctypes.h"
1.29 +#include "shared.h"
1.30 +#include "msgservice.h"
1.31 +#include "cusbhostmslogicalunit.h"
1.32 +#include "cusbhostmsdevice.h"
1.33 +#include "msdebug.h"
1.34 +#include "cusbhostmssession.h"
1.35 +#include "cusbhostmsdevicethread.h"
1.36 +#include "debug.h"
1.37 +
1.38 +/**
1.39 +Constructor
1.40 +*/
1.41 +TDeviceHandler::TDeviceHandler(CUsbHostMsDevice& aDevice)
1.42 +: iDevice(aDevice)
1.43 + {
1.44 + __MSFNLOG
1.45 + }
1.46 +
1.47 +
1.48 +/**
1.49 + Services messages directed to a device. Messages associated with a single
1.50 + Logical Unit contained by the device are forwarded to the Logical Unit
1.51 + Handler.
1.52 +
1.53 + @param aMessage
1.54 + */
1.55 +void TDeviceHandler::HandleMessageL(const RMessage2& aMessage)
1.56 + {
1.57 + __MSFNLOG
1.58 + TLun lun = iDevice.GetAndSetLunL(aMessage);
1.59 +
1.60 + switch (aMessage.Function())
1.61 + {
1.62 + case EUsbHostMsSuspendLun:
1.63 + iDevice.SuspendLunL(lun);
1.64 + break;
1.65 + case EUsbHostMsUnRegisterLun:
1.66 + iDevice.RemoveLunL(lun);
1.67 + break;
1.68 + default:
1.69 + // Try Logical Unit Handler
1.70 + CUsbHostMsLogicalUnit& lu = iDevice.GetLuL(lun);
1.71 + TLogicalUnitHandler luHandler(lu);
1.72 + luHandler.HandleMessageL(aMessage);
1.73 + break;
1.74 + }
1.75 + }
1.76 +
1.77 +
1.78 +/**
1.79 + Constructor
1.80 +
1.81 + @param aLu Reference to the logical unit object
1.82 + */
1.83 +TLogicalUnitHandler::TLogicalUnitHandler(CUsbHostMsLogicalUnit& aLu)
1.84 +: iLu(aLu)
1.85 + {
1.86 + __MSFNLOG
1.87 + }
1.88 +
1.89 +
1.90 +/**
1.91 + Services messages directed to a specific Logical Unit. Unrecognized messages
1.92 + will cause a PANIC.
1.93 +
1.94 + @param aMessage
1.95 + */
1.96 +void TLogicalUnitHandler::HandleMessageL(const RMessage2& aMessage)
1.97 + {
1.98 + __MSFNLOG
1.99 + switch (aMessage.Function())
1.100 + {
1.101 + case EUsbHostMsNotifyChange:
1.102 + iLu.NotifyChange(aMessage);
1.103 + break;
1.104 + case EUsbHostMsCancelChangeNotifier:
1.105 + iLu.CancelChangeNotifierL();
1.106 + break;
1.107 + case EUsbHostMsForceRemount:
1.108 + iLu.ForceCompleteNotifyChangeL();
1.109 + break;
1.110 + case EUsbHostMsRead:
1.111 + iLu.ReadL(aMessage);
1.112 + break;
1.113 + case EUsbHostMsWrite:
1.114 + iLu.WriteL(aMessage);
1.115 + break;
1.116 + case EUsbHostMsErase:
1.117 + iLu.EraseL(aMessage);
1.118 + break;
1.119 + case EUsbHostMsCapacity:
1.120 + iLu.CapsL(aMessage);
1.121 + break;
1.122 + default:
1.123 + aMessage.Panic(KUsbHostMsSrvPncCat, EUsbMsPanicIllegalIPC);
1.124 + break;
1.125 + }
1.126 + }
1.127 +
1.128 +
1.129 +void CUsbHostMsDeviceThread::DoStartServerL(TAny* aPtr)
1.130 + {
1.131 + __MSFNSLOG
1.132 + CActiveScheduler* s = new(ELeave) CActiveScheduler;
1.133 + CActiveScheduler::Install(s);
1.134 +
1.135 + CUsbHostMsDeviceThread* iThread = (CUsbHostMsDeviceThread*)aPtr;
1.136 + CActiveScheduler::Add(iThread);
1.137 +
1.138 + iThread->Start();
1.139 +
1.140 + RThread::Rendezvous(KErrNone);
1.141 +
1.142 + //
1.143 + // Ready to run
1.144 + CActiveScheduler::Start();
1.145 +
1.146 + //
1.147 + // Cleanup the scheduler
1.148 + delete s;
1.149 + }
1.150 +
1.151 +
1.152 +TInt CUsbHostMsDeviceThread::Entry(TAny* aPtr)
1.153 + {
1.154 + __MSFNSLOG
1.155 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.156 + if (!cleanup)
1.157 + {
1.158 + return KErrNoMemory;
1.159 + }
1.160 +
1.161 + TRAPD(error, DoStartServerL(aPtr));
1.162 + delete cleanup;
1.163 + return error;
1.164 + }
1.165 +
1.166 +
1.167 +void CUsbHostMsDeviceThread::RunL()
1.168 + {
1.169 + __MSFNLOG
1.170 +
1.171 + // called on completion of MessageRequest() or Resume()
1.172 + User::LeaveIfError(iStatus.Int());
1.173 +
1.174 + Lock();
1.175 + if (iUsbHostMsDevice)
1.176 + {
1.177 + if (iUsbHostMsDevice->IsSuspended())
1.178 + {
1.179 + // request resume
1.180 + Unlock();
1.181 + iUsbHostMsDevice->Resume(iStatus);
1.182 + SetActive();
1.183 + return;
1.184 + }
1.185 + }
1.186 +
1.187 + // process message queue
1.188 + RMessage2 msg = iRMessage2[iDequeueIndex];
1.189 +
1.190 + iDequeueIndex++;
1.191 +
1.192 + if(iDequeueIndex >= KMaxNumMessage)
1.193 + iDequeueIndex = 0;
1.194 + if(iQueueFull)
1.195 + iQueueFull = EFalse;
1.196 +
1.197 + HandleMessage(msg);
1.198 +
1.199 + if ((iQueueIndex != iDequeueIndex) || iQueueFull)
1.200 + {
1.201 + // self completion
1.202 + TRequestStatus* status = &iStatus;
1.203 + User::RequestComplete(status, KErrNone);
1.204 + SetActive();
1.205 + }
1.206 + else
1.207 + {
1.208 + iUsbHostMsSession.MessageRequest(iStatus);
1.209 + SetActive();
1.210 + }
1.211 + Unlock();
1.212 + }
1.213 +
1.214 +
1.215 +void CUsbHostMsDeviceThread::DoCancel()
1.216 + {
1.217 + TRequestStatus* status = &iStatus;
1.218 + User::RequestComplete(status, KErrCancel);
1.219 + }
1.220 +
1.221 +
1.222 +TInt CUsbHostMsDeviceThread::RunError(TInt aError)
1.223 +{
1.224 + __HOSTPRINT1(_L(">> HOST RunError returning %d"), aError);
1.225 + return KErrNone;
1.226 +}
1.227 +
1.228 +
1.229 +TInt CUsbHostMsDeviceThread::QueueMsg(const RMessage2& aMsg)
1.230 + {
1.231 + __MSFNLOG
1.232 +
1.233 + if (iQueueFull)
1.234 + {
1.235 + return KErrOverflow;
1.236 + }
1.237 +
1.238 + Lock();
1.239 +
1.240 + iRMessage2[iQueueIndex] = aMsg;
1.241 + iQueueIndex++;
1.242 +
1.243 + if (iQueueIndex >= KMaxNumMessage)
1.244 + {
1.245 + iQueueIndex = 0;
1.246 + }
1.247 +
1.248 + if (iQueueIndex == iDequeueIndex)
1.249 + {
1.250 + iQueueFull = ETrue;
1.251 + }
1.252 + Unlock();
1.253 + return KErrNone;
1.254 + }
1.255 +
1.256 +
1.257 +CUsbHostMsDeviceThread::CUsbHostMsDeviceThread(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
1.258 +: CActive(EPriorityStandard),
1.259 + iUsbHostMsSession(aUsbHostMsSession),
1.260 + iQueueFull(EFalse)
1.261 + {
1.262 + __MSFNLOG
1.263 + TBuf<32> nameBuf;
1.264 + nameBuf.Format(_L("Host Ms ThreadMutex%8x"), aToken);
1.265 + iMutex.CreateGlobal(nameBuf,EOwnerProcess);
1.266 + }
1.267 +
1.268 +CUsbHostMsDeviceThread::~CUsbHostMsDeviceThread()
1.269 + {
1.270 + __MSFNLOG
1.271 + Cancel();
1.272 + iMutex.Close();
1.273 + }
1.274 +
1.275 +CUsbHostMsDeviceThread* CUsbHostMsDeviceThread::NewL(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
1.276 + {
1.277 + __MSFNSLOG
1.278 + CUsbHostMsDeviceThread* r = new (ELeave) CUsbHostMsDeviceThread(aUsbHostMsSession, aToken);
1.279 + return r;
1.280 + }
1.281 +
1.282 +
1.283 +void CUsbHostMsDeviceThread::Start()
1.284 + {
1.285 + iUsbHostMsSession.MessageRequest(iStatus);
1.286 + SetActive();
1.287 + }
1.288 +
1.289 +
1.290 +/**
1.291 + Handles the request (in the form of a message) received from the client
1.292 +@param aMessage The received message
1.293 + */
1.294 +void CUsbHostMsDeviceThread::HandleMessage(const RMessage2& aMessage)
1.295 + {
1.296 + __MSFNLOG
1.297 + TInt ret = KErrNotReady;
1.298 + __HOSTPRINT2(_L(">> HOST DispatchMessageL Function=%d %d"), aMessage.Function(), aMessage.Int3());
1.299 + switch (aMessage.Function())
1.300 + {
1.301 + case EUsbHostMsRegisterInterface:
1.302 + TRAP(ret, RegisterInterfaceL(aMessage));
1.303 + break;
1.304 + case EUsbHostMsInitialiseInterface:
1.305 + TRAP(ret, InitialiseInterfaceL(aMessage));
1.306 + // CUsbInterfaceHandler::GetMaxLun() completes asynchronously
1.307 + if (ret)
1.308 + {
1.309 + // Error condition needs to be completed
1.310 + break;
1.311 + }
1.312 + return;
1.313 + case EUsbHostMsUnRegisterInterface:
1.314 + TRAP(ret, UnRegisterInterfaceL(aMessage));
1.315 + break;
1.316 + case EUsbHostMsRegisterLun:
1.317 + TRAP(ret, RegisterLogicalUnitL(aMessage));
1.318 + break;
1.319 + case EUsbHostMsGetNumLun:
1.320 + TRAP(ret, GetNumLunL(aMessage));
1.321 + break;
1.322 + case EUsbHostMsShutdown:
1.323 + ret = Shutdown();
1.324 + break;
1.325 + default:
1.326 + // Try Device Handler and Logical Unit Handler
1.327 + __ASSERT_DEBUG(iUsbHostMsDevice, User::Invariant());
1.328 + TDeviceHandler deviceHandler(*iUsbHostMsDevice);
1.329 + TRAP(ret, deviceHandler.HandleMessageL(aMessage));
1.330 + break;
1.331 + }
1.332 + __HOSTPRINT1(_L(">> HOST returning %d"), ret);
1.333 +
1.334 + if (aMessage.Function() != EUsbHostMsNotifyChange)
1.335 + {
1.336 + aMessage.Complete(ret);
1.337 + }
1.338 + }
1.339 +
1.340 +
1.341 +/**
1.342 +Client request to shut down the server
1.343 +
1.344 +return KErrNone
1.345 +*/
1.346 +TInt CUsbHostMsDeviceThread::Shutdown()
1.347 + {
1.348 + __MSFNLOG
1.349 + CActiveScheduler::Stop();
1.350 + return KErrNone;
1.351 + }
1.352 +
1.353 +void CUsbHostMsDeviceThread::GetNumLunL(const RMessage2& aMessage)
1.354 + {
1.355 + __MSFNLOG
1.356 + if (!iUsbHostMsDevice)
1.357 + {
1.358 + User::Leave(KErrNotReady);
1.359 + }
1.360 +
1.361 + TUint32 maxLun = iUsbHostMsDevice->GetMaxLun() + 1;
1.362 + TPtrC8 pLun((TUint8*)&maxLun,sizeof(TUint32));
1.363 + aMessage.WriteL(0,pLun);
1.364 + }
1.365 +
1.366 +
1.367 +void CUsbHostMsDeviceThread::RegisterInterfaceL(const RMessage2& aMessage)
1.368 + {
1.369 + __MSFNLOG
1.370 +
1.371 + THostMassStorageConfig msDeviceConfig;
1.372 + TPtr8 ptr((TUint8*)&msDeviceConfig,sizeof(THostMassStorageConfig));
1.373 + aMessage.ReadL(0, ptr);
1.374 +
1.375 + __HOSTPRINT1(_L("RegisterInterfaceL Token=%d "), msDeviceConfig.iInterfaceToken);
1.376 +
1.377 + iUsbHostMsDevice = CUsbHostMsDevice::NewL(msDeviceConfig);
1.378 + }
1.379 +
1.380 +
1.381 +void CUsbHostMsDeviceThread::InitialiseInterfaceL(const RMessage2& aMessage)
1.382 + {
1.383 + __MSFNLOG
1.384 + if (!iUsbHostMsDevice)
1.385 + {
1.386 + User::Leave(KErrNotReady);
1.387 + }
1.388 +
1.389 + TRAPD(err, iUsbHostMsDevice->InitialiseL(aMessage));
1.390 + if (err != KErrNone)
1.391 + {
1.392 + delete iUsbHostMsDevice;
1.393 + iUsbHostMsDevice = NULL;
1.394 + User::Leave(err);
1.395 + }
1.396 + }
1.397 +
1.398 +
1.399 +void CUsbHostMsDeviceThread::UnRegisterInterfaceL(const RMessage2& aMessage)
1.400 + {
1.401 + __MSFNLOG
1.402 + if (!iUsbHostMsDevice)
1.403 + {
1.404 + User::Leave(KErrNotReady);
1.405 + }
1.406 +
1.407 + TRAPD(err, iUsbHostMsDevice->UnInitialiseL());
1.408 + delete iUsbHostMsDevice;
1.409 + iUsbHostMsDevice = NULL;
1.410 + User::LeaveIfError(err);
1.411 + }
1.412 +
1.413 +
1.414 +void CUsbHostMsDeviceThread::RegisterLogicalUnitL(const RMessage2& aMessage)
1.415 + {
1.416 + if (!iUsbHostMsDevice)
1.417 + {
1.418 + User::Leave(KErrNotReady);
1.419 + }
1.420 +
1.421 + TUint32 iLunId = aMessage.Int0() + 1; // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
1.422 + TPtrC8 pLun((TUint8*)&iLunId, sizeof(TUint32));
1.423 + aMessage.WriteL(3, pLun);
1.424 + iLunId -= 1; // We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT
1.425 + iUsbHostMsDevice->AddLunL(iLunId);
1.426 + iUsbHostMsDevice->InitLunL(iLunId);
1.427 + }
1.428 +