os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/controller/cusbhostmsdevicethread.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Implements a Session of a Symbian OS server for the RUsbMassStorage API
sl@0
    15
//
sl@0
    16
//
sl@0
    17
sl@0
    18
/**
sl@0
    19
 @file
sl@0
    20
 @internalTechnology
sl@0
    21
*/
sl@0
    22
sl@0
    23
#include <e32base.h>
sl@0
    24
sl@0
    25
#include "msctypes.h"
sl@0
    26
#include "shared.h"
sl@0
    27
#include "msgservice.h"
sl@0
    28
#include "cusbhostmslogicalunit.h"
sl@0
    29
#include "cusbhostmsdevice.h"
sl@0
    30
#include "msdebug.h"
sl@0
    31
#include "cusbhostmssession.h"
sl@0
    32
#include "cusbhostmsdevicethread.h"
sl@0
    33
#include "debug.h"
sl@0
    34
sl@0
    35
/**
sl@0
    36
Constructor
sl@0
    37
*/
sl@0
    38
TDeviceHandler::TDeviceHandler(CUsbHostMsDevice& aDevice)
sl@0
    39
:   iDevice(aDevice)
sl@0
    40
    {
sl@0
    41
    __MSFNLOG
sl@0
    42
    }
sl@0
    43
sl@0
    44
sl@0
    45
/**
sl@0
    46
   Services messages directed to a device. Messages associated with a single
sl@0
    47
   Logical Unit contained by the device are forwarded to the Logical Unit
sl@0
    48
   Handler.
sl@0
    49
sl@0
    50
   @param aMessage
sl@0
    51
 */
sl@0
    52
void TDeviceHandler::HandleMessageL(const RMessage2& aMessage)
sl@0
    53
    {
sl@0
    54
    __MSFNLOG
sl@0
    55
    TLun lun = iDevice.GetAndSetLunL(aMessage);
sl@0
    56
sl@0
    57
	switch (aMessage.Function())
sl@0
    58
		{
sl@0
    59
	case EUsbHostMsSuspendLun:
sl@0
    60
        iDevice.SuspendLunL(lun);
sl@0
    61
		break;
sl@0
    62
    case EUsbHostMsUnRegisterLun:
sl@0
    63
        iDevice.RemoveLunL(lun);
sl@0
    64
        break;
sl@0
    65
    default:
sl@0
    66
        // Try Logical Unit Handler
sl@0
    67
        CUsbHostMsLogicalUnit& lu = iDevice.GetLuL(lun);
sl@0
    68
        TLogicalUnitHandler luHandler(lu);
sl@0
    69
        luHandler.HandleMessageL(aMessage);
sl@0
    70
		break;
sl@0
    71
		}
sl@0
    72
    }
sl@0
    73
sl@0
    74
sl@0
    75
/**
sl@0
    76
   Constructor
sl@0
    77
sl@0
    78
   @param aLu Reference to the logical unit object
sl@0
    79
 */
sl@0
    80
TLogicalUnitHandler::TLogicalUnitHandler(CUsbHostMsLogicalUnit& aLu)
sl@0
    81
:   iLu(aLu)
sl@0
    82
    {
sl@0
    83
    __MSFNLOG
sl@0
    84
    }
sl@0
    85
sl@0
    86
sl@0
    87
/**
sl@0
    88
   Services messages directed to a specific Logical Unit. Unrecognized messages
sl@0
    89
   will cause a PANIC.
sl@0
    90
sl@0
    91
   @param aMessage
sl@0
    92
 */
sl@0
    93
void TLogicalUnitHandler::HandleMessageL(const RMessage2& aMessage)
sl@0
    94
	{
sl@0
    95
    __MSFNLOG
sl@0
    96
	switch (aMessage.Function())
sl@0
    97
		{
sl@0
    98
	case EUsbHostMsNotifyChange:
sl@0
    99
        iLu.NotifyChange(aMessage);
sl@0
   100
		break;
sl@0
   101
	case EUsbHostMsCancelChangeNotifier:
sl@0
   102
        iLu.CancelChangeNotifierL();
sl@0
   103
		break;
sl@0
   104
	case EUsbHostMsForceRemount:
sl@0
   105
        iLu.ForceCompleteNotifyChangeL();
sl@0
   106
		break;
sl@0
   107
	case EUsbHostMsRead:
sl@0
   108
        iLu.ReadL(aMessage);
sl@0
   109
		break;
sl@0
   110
	case EUsbHostMsWrite:
sl@0
   111
        iLu.WriteL(aMessage);
sl@0
   112
		break;
sl@0
   113
	case EUsbHostMsErase:
sl@0
   114
        iLu.EraseL(aMessage);
sl@0
   115
		break;
sl@0
   116
	case EUsbHostMsCapacity:
sl@0
   117
        iLu.CapsL(aMessage);
sl@0
   118
		break;
sl@0
   119
	default:
sl@0
   120
		aMessage.Panic(KUsbHostMsSrvPncCat, EUsbMsPanicIllegalIPC);
sl@0
   121
		break;
sl@0
   122
		}
sl@0
   123
	}
sl@0
   124
sl@0
   125
sl@0
   126
void CUsbHostMsDeviceThread::DoStartServerL(TAny* aPtr)
sl@0
   127
    {
sl@0
   128
    __MSFNSLOG
sl@0
   129
    CActiveScheduler* s = new(ELeave) CActiveScheduler;
sl@0
   130
    CActiveScheduler::Install(s);
sl@0
   131
sl@0
   132
	CUsbHostMsDeviceThread* iThread = (CUsbHostMsDeviceThread*)aPtr;
sl@0
   133
	CActiveScheduler::Add(iThread);
sl@0
   134
sl@0
   135
    iThread->Start();
sl@0
   136
sl@0
   137
	RThread::Rendezvous(KErrNone);
sl@0
   138
sl@0
   139
	//
sl@0
   140
    // Ready to run
sl@0
   141
    CActiveScheduler::Start();
sl@0
   142
sl@0
   143
    //
sl@0
   144
    // Cleanup the scheduler
sl@0
   145
	delete s;
sl@0
   146
    }
sl@0
   147
sl@0
   148
sl@0
   149
TInt CUsbHostMsDeviceThread::Entry(TAny* aPtr)
sl@0
   150
	{
sl@0
   151
    __MSFNSLOG
sl@0
   152
	CTrapCleanup* cleanup = CTrapCleanup::New();
sl@0
   153
    if (!cleanup)
sl@0
   154
        {
sl@0
   155
        return KErrNoMemory;
sl@0
   156
        }
sl@0
   157
sl@0
   158
    TRAPD(error, DoStartServerL(aPtr));
sl@0
   159
    delete cleanup;
sl@0
   160
    return error;
sl@0
   161
	}
sl@0
   162
sl@0
   163
sl@0
   164
void  CUsbHostMsDeviceThread::RunL()
sl@0
   165
	{
sl@0
   166
    __MSFNLOG
sl@0
   167
sl@0
   168
    // called on completion of MessageRequest() or Resume()
sl@0
   169
    User::LeaveIfError(iStatus.Int());
sl@0
   170
sl@0
   171
	Lock();    
sl@0
   172
    if (iUsbHostMsDevice)
sl@0
   173
        {
sl@0
   174
        if (iUsbHostMsDevice->IsSuspended())
sl@0
   175
            {
sl@0
   176
            // request resume 
sl@0
   177
            Unlock();
sl@0
   178
            iUsbHostMsDevice->Resume(iStatus);
sl@0
   179
            SetActive();
sl@0
   180
            return;
sl@0
   181
            }
sl@0
   182
        }
sl@0
   183
sl@0
   184
    // process message queue
sl@0
   185
    RMessage2 msg = iRMessage2[iDequeueIndex];
sl@0
   186
sl@0
   187
    iDequeueIndex++;
sl@0
   188
sl@0
   189
    if(iDequeueIndex >= KMaxNumMessage)
sl@0
   190
     	iDequeueIndex = 0;
sl@0
   191
    if(iQueueFull)
sl@0
   192
     	iQueueFull = EFalse;
sl@0
   193
sl@0
   194
    HandleMessage(msg);
sl@0
   195
sl@0
   196
    if ((iQueueIndex != iDequeueIndex) || iQueueFull)
sl@0
   197
	   	{
sl@0
   198
        // self completion        
sl@0
   199
        TRequestStatus* status = &iStatus;
sl@0
   200
        User::RequestComplete(status, KErrNone);
sl@0
   201
        SetActive();
sl@0
   202
        }
sl@0
   203
    else
sl@0
   204
        {
sl@0
   205
        iUsbHostMsSession.MessageRequest(iStatus);
sl@0
   206
        SetActive();
sl@0
   207
        }
sl@0
   208
    Unlock();
sl@0
   209
	}
sl@0
   210
sl@0
   211
sl@0
   212
void CUsbHostMsDeviceThread::DoCancel()
sl@0
   213
    {
sl@0
   214
    TRequestStatus* status = &iStatus;
sl@0
   215
    User::RequestComplete(status, KErrCancel);
sl@0
   216
    }
sl@0
   217
sl@0
   218
sl@0
   219
TInt CUsbHostMsDeviceThread::RunError(TInt aError)
sl@0
   220
{
sl@0
   221
    __HOSTPRINT1(_L(">> HOST RunError returning %d"), aError);
sl@0
   222
    return KErrNone;
sl@0
   223
}
sl@0
   224
sl@0
   225
sl@0
   226
TInt CUsbHostMsDeviceThread::QueueMsg(const RMessage2& aMsg)
sl@0
   227
	{
sl@0
   228
    __MSFNLOG
sl@0
   229
sl@0
   230
	if (iQueueFull)
sl@0
   231
		{
sl@0
   232
		return KErrOverflow;
sl@0
   233
		}
sl@0
   234
sl@0
   235
    Lock();
sl@0
   236
sl@0
   237
	iRMessage2[iQueueIndex] = aMsg;
sl@0
   238
	iQueueIndex++;
sl@0
   239
sl@0
   240
	if (iQueueIndex >= KMaxNumMessage)
sl@0
   241
		{
sl@0
   242
		iQueueIndex = 0;
sl@0
   243
		}
sl@0
   244
sl@0
   245
	if (iQueueIndex == iDequeueIndex)
sl@0
   246
		{
sl@0
   247
		iQueueFull = ETrue;
sl@0
   248
		}
sl@0
   249
	Unlock();
sl@0
   250
	return KErrNone;
sl@0
   251
	}
sl@0
   252
sl@0
   253
sl@0
   254
CUsbHostMsDeviceThread::CUsbHostMsDeviceThread(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
sl@0
   255
:	CActive(EPriorityStandard),
sl@0
   256
    iUsbHostMsSession(aUsbHostMsSession),
sl@0
   257
    iQueueFull(EFalse)
sl@0
   258
	{
sl@0
   259
    __MSFNLOG
sl@0
   260
    TBuf<32> nameBuf;
sl@0
   261
    nameBuf.Format(_L("Host Ms ThreadMutex%8x"), aToken);
sl@0
   262
	iMutex.CreateGlobal(nameBuf,EOwnerProcess);
sl@0
   263
	}
sl@0
   264
sl@0
   265
CUsbHostMsDeviceThread::~CUsbHostMsDeviceThread()
sl@0
   266
	{
sl@0
   267
    __MSFNLOG
sl@0
   268
    Cancel();
sl@0
   269
	iMutex.Close();
sl@0
   270
	}
sl@0
   271
sl@0
   272
CUsbHostMsDeviceThread* CUsbHostMsDeviceThread::NewL(CUsbHostMsSession& aUsbHostMsSession, TUint aToken)
sl@0
   273
	{
sl@0
   274
    __MSFNSLOG
sl@0
   275
	CUsbHostMsDeviceThread* r = new (ELeave) CUsbHostMsDeviceThread(aUsbHostMsSession, aToken);
sl@0
   276
	return r;
sl@0
   277
	}
sl@0
   278
sl@0
   279
sl@0
   280
void CUsbHostMsDeviceThread::Start()
sl@0
   281
    {
sl@0
   282
    iUsbHostMsSession.MessageRequest(iStatus);
sl@0
   283
    SetActive();
sl@0
   284
    }
sl@0
   285
sl@0
   286
sl@0
   287
/**
sl@0
   288
 Handles the request (in the form of a message) received from the client
sl@0
   289
@param	aMessage	The received message
sl@0
   290
 */
sl@0
   291
void CUsbHostMsDeviceThread::HandleMessage(const RMessage2& aMessage)
sl@0
   292
	{
sl@0
   293
    __MSFNLOG
sl@0
   294
	TInt ret = KErrNotReady;
sl@0
   295
    __HOSTPRINT2(_L(">> HOST DispatchMessageL Function=%d %d"), aMessage.Function(), aMessage.Int3());
sl@0
   296
	switch (aMessage.Function())
sl@0
   297
		{
sl@0
   298
	case EUsbHostMsRegisterInterface:
sl@0
   299
		TRAP(ret, RegisterInterfaceL(aMessage));
sl@0
   300
		break;
sl@0
   301
    case EUsbHostMsInitialiseInterface:
sl@0
   302
		TRAP(ret, InitialiseInterfaceL(aMessage));
sl@0
   303
        // CUsbInterfaceHandler::GetMaxLun() completes asynchronously
sl@0
   304
        if (ret)
sl@0
   305
            {
sl@0
   306
            // Error condition needs to be completed
sl@0
   307
            break;
sl@0
   308
            }
sl@0
   309
		return;
sl@0
   310
	case EUsbHostMsUnRegisterInterface:
sl@0
   311
		TRAP(ret, UnRegisterInterfaceL(aMessage));
sl@0
   312
		break;
sl@0
   313
	case EUsbHostMsRegisterLun:
sl@0
   314
		TRAP(ret, RegisterLogicalUnitL(aMessage));
sl@0
   315
		break;
sl@0
   316
	case EUsbHostMsGetNumLun:
sl@0
   317
		TRAP(ret, GetNumLunL(aMessage));
sl@0
   318
		break;
sl@0
   319
	case EUsbHostMsShutdown:
sl@0
   320
		ret = Shutdown();
sl@0
   321
		break;
sl@0
   322
    default:
sl@0
   323
        // Try Device Handler and Logical Unit Handler
sl@0
   324
        __ASSERT_DEBUG(iUsbHostMsDevice, User::Invariant());
sl@0
   325
        TDeviceHandler deviceHandler(*iUsbHostMsDevice);
sl@0
   326
        TRAP(ret, deviceHandler.HandleMessageL(aMessage));
sl@0
   327
		break;
sl@0
   328
		}
sl@0
   329
    __HOSTPRINT1(_L(">> HOST returning %d"), ret);
sl@0
   330
sl@0
   331
    if (aMessage.Function() != EUsbHostMsNotifyChange)
sl@0
   332
        {
sl@0
   333
        aMessage.Complete(ret);
sl@0
   334
        }
sl@0
   335
	}
sl@0
   336
sl@0
   337
sl@0
   338
/**
sl@0
   339
Client request to shut down the server
sl@0
   340
sl@0
   341
return KErrNone
sl@0
   342
*/
sl@0
   343
TInt CUsbHostMsDeviceThread::Shutdown()
sl@0
   344
    {
sl@0
   345
    __MSFNLOG
sl@0
   346
    CActiveScheduler::Stop();
sl@0
   347
	return KErrNone;
sl@0
   348
	}
sl@0
   349
sl@0
   350
void CUsbHostMsDeviceThread::GetNumLunL(const RMessage2& aMessage)
sl@0
   351
	{
sl@0
   352
	__MSFNLOG
sl@0
   353
    if (!iUsbHostMsDevice)
sl@0
   354
        {
sl@0
   355
        User::Leave(KErrNotReady);
sl@0
   356
        }
sl@0
   357
sl@0
   358
	TUint32 maxLun = iUsbHostMsDevice->GetMaxLun() + 1;
sl@0
   359
	TPtrC8 pLun((TUint8*)&maxLun,sizeof(TUint32));
sl@0
   360
	aMessage.WriteL(0,pLun);
sl@0
   361
	}
sl@0
   362
sl@0
   363
sl@0
   364
void CUsbHostMsDeviceThread::RegisterInterfaceL(const RMessage2& aMessage)
sl@0
   365
	{
sl@0
   366
	__MSFNLOG
sl@0
   367
sl@0
   368
	THostMassStorageConfig msDeviceConfig;
sl@0
   369
	TPtr8 ptr((TUint8*)&msDeviceConfig,sizeof(THostMassStorageConfig));
sl@0
   370
	aMessage.ReadL(0, ptr);
sl@0
   371
sl@0
   372
    __HOSTPRINT1(_L("RegisterInterfaceL Token=%d "), msDeviceConfig.iInterfaceToken);
sl@0
   373
sl@0
   374
	iUsbHostMsDevice = CUsbHostMsDevice::NewL(msDeviceConfig);
sl@0
   375
	}
sl@0
   376
sl@0
   377
sl@0
   378
void CUsbHostMsDeviceThread::InitialiseInterfaceL(const RMessage2& aMessage)
sl@0
   379
	{
sl@0
   380
	__MSFNLOG
sl@0
   381
    if (!iUsbHostMsDevice)
sl@0
   382
        {
sl@0
   383
        User::Leave(KErrNotReady);
sl@0
   384
        }
sl@0
   385
sl@0
   386
	TRAPD(err, iUsbHostMsDevice->InitialiseL(aMessage));
sl@0
   387
    if (err != KErrNone)
sl@0
   388
        {
sl@0
   389
        delete iUsbHostMsDevice;
sl@0
   390
		iUsbHostMsDevice = NULL;
sl@0
   391
        User::Leave(err);
sl@0
   392
        }
sl@0
   393
	}
sl@0
   394
sl@0
   395
sl@0
   396
void CUsbHostMsDeviceThread::UnRegisterInterfaceL(const RMessage2& aMessage)
sl@0
   397
    {
sl@0
   398
    __MSFNLOG
sl@0
   399
    if (!iUsbHostMsDevice)
sl@0
   400
        {
sl@0
   401
        User::Leave(KErrNotReady);
sl@0
   402
        }
sl@0
   403
sl@0
   404
	TRAPD(err, iUsbHostMsDevice->UnInitialiseL());
sl@0
   405
	delete iUsbHostMsDevice;
sl@0
   406
	iUsbHostMsDevice = NULL;
sl@0
   407
    User::LeaveIfError(err);
sl@0
   408
    }
sl@0
   409
sl@0
   410
sl@0
   411
void CUsbHostMsDeviceThread::RegisterLogicalUnitL(const RMessage2& aMessage)
sl@0
   412
	{
sl@0
   413
    if (!iUsbHostMsDevice)
sl@0
   414
        {
sl@0
   415
        User::Leave(KErrNotReady);
sl@0
   416
        }
sl@0
   417
sl@0
   418
	TUint32 iLunId = aMessage.Int0() + 1; // Subssessions need a positive value to store in the handles. We represent Luns as LunId+1
sl@0
   419
	TPtrC8 pLun((TUint8*)&iLunId, sizeof(TUint32));
sl@0
   420
	aMessage.WriteL(3, pLun);
sl@0
   421
	iLunId -= 1;	// We represent LunId in MSC from 0 to MaxLun-1 as represented in BOT
sl@0
   422
	iUsbHostMsDevice->AddLunL(iLunId);
sl@0
   423
	iUsbHostMsDevice->InitLunL(iLunId);
sl@0
   424
	}
sl@0
   425