// Copyright (c) 1998-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:
// e32\drivers\pbus\pbusmedia.cpp
//
//
#include <drivers/pbusmedia.h>
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "locmedia_ost.h"
#ifdef __VC32__
#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
#endif
#include "pbusmediaTraces.h"
#endif
void mediaCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
{
OstTraceFunctionEntry0( MEDIACALLBACK_ENTRY );
DPBusPrimaryMedia* pM=(DPBusPrimaryMedia*)aPtr;
__KTRACE_OPT(KLOCDRV,Kern::Printf("mediaCallBack media %d, reason %d, a1=0x%x, a2=0x%x",pM->iMediaId,aReason,a1,a2));
OstTraceExt4( TRACE_INTERNALS, MEDIACALLBACK, "aPtr=0x%x; aReason=%d; a1=0x%x; a2=0x%x", ( TUint )( aPtr ), aReason, ( TUint )( a1 ), ( TUint )( a2 ) );
switch (aReason)
{
case TPBusCallBack::EPBusStateChange:
pM->PBusStateChange((TInt)a1,(TInt)a2);
break;
}
OstTraceFunctionExit0( MEDIACALLBACK_EXIT );
}
/**
Constructor for DPBusPrimaryMedia. Initializes the iSocket with aSocket.
@param aSocket Pointer to DPBusSocket object
@see DPBusPrimaryMedia::iSocket
*/
DPBusPrimaryMedia::DPBusPrimaryMedia(DPBusSocket* aSocket)
: iSocket(aSocket)
{
OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_DPBUSPRIMARYMEDIA_ENTRY, this );
}
/**
This function install a media call back for a removable media device.
@param aDevice Local media ID.
@param aMediaId Media Id (unique for a media subsystem)
@param aLastMediaId This indicates number of used media ids+ number of DMedia objects to be associated with the media driver
@return KErrNone if successful,
otherwise one of the other system wide error codes.
@see DPrimaryMediaBase::Create()
*/
TInt DPBusPrimaryMedia::Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId)
{
OstTraceExt4(TRACE_FLOW, DPBUSPRIMARYMEDIA_CREATE_ENTRY ,"DPBusPrimaryMedia::Create;aDevice=%d;aMediaId=%d;aLastMediaId=%d;this=%x", (TInt) aDevice, aMediaId, aLastMediaId, (TUint) this);
// Permanently install a media call back if for a removable media device
TInt r=KErrArgument;
iPBusState=EPBusCardAbsent;
if (__IS_REMOVABLE(aDevice))
{
iBusCallBack.iFunction=mediaCallBack;
iBusCallBack.iPtr=this;
iBusCallBack.SetSocket(iSocket->iSocketNumber);
iDfcQ=&iSocket->iDfcQ;
r=DPrimaryMediaBase::Create(aDevice,aMediaId,aLastMediaId);
if (r==KErrNone)
{
iBusCallBack.Add();
iPBusState=iSocket->State();
iMsgQ.Receive();
}
}
OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_CREATE_EXIT, this, r );
return r;
}
/**
Checks the PBUS state.
@return KErrNone if successful,
KErrNotReady if card is absent.
@see TPBusState
*/
TInt DPBusPrimaryMedia::QuickCheckStatus()
{
OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS_ENTRY, this );
TInt r=KErrNone;
if (iSocket && iSocket->State()==EPBusCardAbsent)
r=KErrNotReady;
__KTRACE_OPT(KLOCDRV,Kern::Printf("DPBusPrimaryMedia::QuickCheckStatus media %d returns %d",iMediaId,r));
OstTraceExt2(TRACE_INTERNALS, DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS, "iMediaId=%d; retval=%d",iMediaId,r);
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_QUICKCHECKSTATUS_EXIT, this );
return r;
}
/**
This function is called by the local media device driver to force a remount of the media device.
@param aFlags Corresponds to force media change.
@return KErrNone if successful,
otherwise one of the other system wide error codes.
@see TForceMediaChangeFlags
*/
TInt DPBusPrimaryMedia::ForceMediaChange(TInt aFlags)
{
OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_ENTRY, this );
if ((aFlags != KMediaRemountForceMediaChange) || (iPBusState == EPBusCardAbsent))
{
TInt pbusState = iPBusState;
// This should ensure NotifyMediaChange() is called for ALL primary media attached to this socket
iSocket->ChangeState(EPBusCardAbsent, KErrNotReady);
// If a request was cancelled it's possible that the socket controller has been left in an
// unusable state which might cause the next request to fail, so power down the socket to be safe
iSocket->ResetSocket(EFalse);
iSocket->ChangeState(pbusState == EPBusCardAbsent ? EPBusCardAbsent : EPBusOff, KErrNotReady);
OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_EXIT1, this, KErrCompletion );
return KErrCompletion;
}
iSocket->ForceMediaChange();
OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_FORCEMEDIACHANGE_EXIT2, this, KErrNone );
return KErrNone;
}
/**
Called by clients to power up the PBUS.
@return KErrNone if successful,
otherwise one of the other system wide error codes.
@see DPBusSocket::PowerUp()
*/
TInt DPBusPrimaryMedia::InitiatePowerUp()
{
OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_INITIATEPOWERUP_ENTRY, this );
TInt r = iSocket->PowerUp();
OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_INITIATEPOWERUP_EXIT, this, r );
return r;
}
/**
Flags the media driver as entering a critical part of its processing.
@return KErrNone if successful,
otherwise one of the other system wide error codes.
@see DPBusSocket::InCritical()
*/
TInt DPBusPrimaryMedia::DoInCritical()
{
OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DOINCRITICAL_ENTRY, this );
TInt r = iSocket->InCritical();
OstTraceFunctionExitExt( DPBUSPRIMARYMEDIA_DOINCRITICAL_EXIT, this, r );
return r;
}
/**
Flags the media driver as leaving a critical part of its processing.
@return KErrNone if successful,
otherwise one of the other system wide error codes.
@see DPBusSocket::EndInCritical()
*/
void DPBusPrimaryMedia::DoEndInCritical()
{
OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DOENDINCRITICAL_ENTRY, this );
iSocket->EndInCritical();
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DOENDINCRITICAL_EXIT, this );
}
/**
Sets the incremental value of current consumption to aCurrent.
@param aCurrent Delta Current in Milliamps.
@see DPBusSocket::DeltaCurrentConsumption()
*/
void DPBusPrimaryMedia::DeltaCurrentConsumption(TInt aCurrent)
{
OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_DELTACURRENTCONSUMPTION_ENTRY, this );
iSocket->DeltaCurrentConsumption(aCurrent);
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DELTACURRENTCONSUMPTION_EXIT, this );
}
/**
Gets the default drive capability/attributes.
@param aCaps A reference to a client-supplied TLocalDriveCapsV2 class to be filled by this function.
@see TLocalDriveCapsV2
@see TMediaType
*/
void DPBusPrimaryMedia::DefaultDriveCaps(TLocalDriveCapsV2& aCaps)
{
OstTraceFunctionEntry1( DPBUSPRIMARYMEDIA_DEFAULTDRIVECAPS_ENTRY, this );
// aCaps is zeroed beforehand
aCaps.iType = EMediaNotPresent;
aCaps.iDriveAtt = KDriveAttLocal|KDriveAttRemovable;
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_DEFAULTDRIVECAPS_EXIT, this );
}
/**
Checks whether it is a removable media device or not.
@param aSocketNum This will be updated with socket number
@return ETrue if Removable Device, EFalse if the device is Non-Removable.
*/
TBool DPBusPrimaryMedia::IsRemovableDevice(TInt& aSocketNum)
{
OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_ISREMOVABLEDEVICE_ENTRY, this );
aSocketNum=iSocket->iSocketNumber;
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_ISREMOVABLEDEVICE_EXIT, this );
return(ETrue);
}
void DPBusPrimaryMedia::PBusStateChange(TInt aState, TInt anError)
{
OstTraceFunctionEntryExt( DPBUSPRIMARYMEDIA_PBUSSTATECHANGE_ENTRY, this );
// receive power down and media change notifications
__KTRACE_OPT(KLOCDRV,Kern::Printf("DPBusPrimaryMedia(%d)::PBusStateChange state %d, err %d",iMediaId,aState,anError));
OstTraceExt3(TRACE_INTERNALS, DPBUSPRIMARYMEDIA_PBUSSTATECHANGE, "iMediaId=%d; aState=%d; anError=%d", iMediaId,aState,anError);
if (aState!=iPBusState)
{
TInt oldState = iPBusState;
iPBusState=aState;
switch (aState)
{
case EPBusCardAbsent:
NotifyMediaChange();
break;
case EPBusOff:
switch (anError)
{
case KErrNone:
// machine power down
NotifyPowerDown();
break;
case KErrTimedOut:
// machine power down
NotifyPowerDown();
if(oldState == EPBusCardAbsent)
{
// powering down after power up with no card present.
// ...to prevent the bus powering up again, maintain
// the card state as absent. A media change will
// update the status to allow the bus to power up.
iPBusState = EPBusCardAbsent;
}
break;
case KErrNotReady:
// card detected following door close
NotifyMediaPresent();
break;
case KErrAbort:
NotifyEmergencyPowerDown();
break;
default:
if (iState==EPoweringUp1 || iState==EPoweringUp2)
PowerUpComplete(anError);
break;
}
case EPBusPoweringUp:
// no action required
break;
case EPBusOn:
// bus is now powered up
if (iState==EPoweringUp1 || iState==EPoweringUp2)
PowerUpComplete(anError);
break;
case EPBusPsuFault:
NotifyPsuFault(anError);
break;
case EPBusPowerUpPending:
// no action required
break;
default:
break;
}
}
OstTraceFunctionExit1( DPBUSPRIMARYMEDIA_PBUSSTATECHANGE_EXIT, this );
}