/*
* Copyright (c) 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:
* Implementation of DMC logical channel.
*
*/
// INCLUDE FILES
#include <kern_priv.h> // class DThread
#include "dmc_extension.h" // iDmcDfcQueuePtrv
#include "dmc_user_if.h"
#include "dmc_logical_channel.h"
#include "dmc_logical_device.h"
#include "dmc_trace.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "dmc_logical_channelTraces.h"
#endif
// EXTERNAL DATA STRUCTURES
// EXTERNAL FUNCTION PROTOTYPES
// FORWARD DECLARATIONS
// CONSTANTS
// MACROS
// LOCAL CONSTANTS AND MACROS
// MODULE DATA STRUCTURES
// LOCAL FUNCTION PROTOTYPES
// ==================== LOCAL FUNCTIONS ====================
// ================= OTHER EXPORTED FUNCTIONS ==============
// ================= MEMBER FUNCTIONS =======================
//-----------------------------------------------------------
// DDmcLogicalChannel::DDmcLogicalChannel
//-----------------------------------------------------------
DDmcLogicalChannel::DDmcLogicalChannel(DLogicalDevice* aLogicalDevicePtr)
: DLogicalChannel()
, iDmcLogicalDevPtr(NULL)
, iClientThreadPtr(NULL)
, iClientStatusPtr(NULL)
, iClientEventBufferPtr(NULL)
{
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DDMC_LOGICAL_CHANNEL_ENTRY,
"DMC:LOGIC_CHNL: DDmcLogicalChannel() # IN - aLogicalDevicePtr, 0x%x:",
aLogicalDevicePtr);
DMC_TRACE((("DMC:LOGIC_CHNL: DDmcLogicalChannel() # IN - aLogicalDevicePtr, 0x%x:"),
aLogicalDevicePtr));
DMC_TRACE_ASSERT(aLogicalDevicePtr);
iDmcLogicalDevPtr = reinterpret_cast<DDmcLogicalDevice*>(aLogicalDevicePtr);
iClientThreadPtr = &Kern::CurrentThread();
TInt result = ((DObject*)iClientThreadPtr)->Open();
DMC_TRACE_ASSERT(result == KErrNone);
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DDMC_LOGICAL_CHANNEL_RETURN,
"DMC:LOGIC_CHNL: DDmcLogicalChannel() # OUT");
DMC_TRACE(("DMC:LOGIC_CHNL: DDmcLogicalChannel() # OUT"));
}
//-----------------------------------------------------------
// DDmcLogicalChannel::~DDmcLogicalChannel
//-----------------------------------------------------------
DDmcLogicalChannel::~DDmcLogicalChannel()
{
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL__DDMC_LOGICAL_CHANNEL_ENTRY,
"DMC:LOGIC_CHNL: ~DDmcLogicalChannel() # IN");
DMC_TRACE(("DMC:LOGIC_CHNL: ~DDmcLogicalChannel() # IN"));
// Calling of Kern::SafeClose must be in a critical section
NKern::ThreadEnterCS();
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DDMC_LOGICAL_CHANNEL_1,
"DMC:LOGIC_CHNL: ~DDmcLogicalChannel() - call Kern::SafeClose");
DMC_TRACE(("DMC:LOGIC_CHNL: ~DDmcLogicalChannel() - call Kern::SafeClose"));
// Close our reference on the client thread
Kern::SafeClose((DObject*&)iClientThreadPtr, NULL);
NKern::ThreadLeaveCS();
// Cancel reset and power off events
iDmcLogicalDevPtr->UnsubscribeEvents(this);
if (iDmcLogicalDevPtr)
{
iDmcLogicalDevPtr = NULL;
}
if (iClientThreadPtr)
{
iClientThreadPtr = NULL;
}
if (iClientStatusPtr)
{
iClientStatusPtr = NULL;
}
if (iClientEventBufferPtr)
{
iClientEventBufferPtr = NULL;
}
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL__DDMC_LOGICAL_CHANNEL_RETURN,
"DMC:LOGIC_CHNL: ~DDmcLogicalChannel() # OUT");
DMC_TRACE(("DMC:LOGIC_CHNL: ~DDmcLogicalChannel() # OUT"));
}
// -----------------------------------------------------------------------------
// DDmcLogicalChannel::DoCreate
// -----------------------------------------------------------------------------
TInt DDmcLogicalChannel::DoCreate(TInt /* aUnit */, const TDesC8* /* aInfo */, const TVersion& aVer)
{
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_CREATE_ENTRY,
"DMC:LOGIC_CHNL: DoCreate() # IN - aVer: 0x%x", (TUint)&(aVer));
DMC_TRACE((("DMC:LOGIC_CHNL: DoCreate() # IN - aVer: 0x%x "), &aVer));
TInt retVal(KErrNone);
// capability security check
if (!Kern::CurrentThreadHasCapability(ECapabilityCommDD,
__PLATSEC_DIAGNOSTIC_STRING("Checked by dmc.ldd") ) )
{
DMC_TRACE_ALWAYS_ASSERT;
retVal = KErrPermissionDenied;
}
// Check version
if (retVal == KErrNone)
{
if (!Kern::QueryVersionSupported(TVersion(RDmc::EMajorVersionNumber,
RDmc::EMinorVersionNumber,
RDmc::EBuildVersionNumber),
aVer))
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CREATE_1,
"DMC:LOGIC_CHNL: DoCreate() - KErrNotSupported");
DMC_TRACE_ALWAYS_ASSERT;
retVal = KErrNotSupported;
}
}
// check user's Vendor ID to ensure that only known client are accessing
if (retVal == KErrNone)
{
TUint32 vendorId = Kern::CurrentThread().iOwningProcess->iS.iVendorId;
OstTrace1(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CREATE_2,
"DMC:LOGIC_CHNL: DoCreate() - vendorId: 0x%x", vendorId);
DMC_TRACE((("DMC:LOGIC_CHNL: DoCreate() - vendorId: 0x%x "), vendorId));
if (vendorId != VID_DEFAULT)
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CREATE_3,
"DMC:LOGIC_CHNL: DoCreate() - VID check FAILED !");
DMC_TRACE(("DMC:LOGIC_CHNL: DoCreate() - VID check FAILED !"));
DMC_TRACE_ALWAYS_ASSERT;
retVal = KErrAccessDenied;
}
}
// Initialize DFC queue
DMC_TRACE_ASSERT_RESET(iDmcLogicalDevPtr->GetDynamicDfcQueue(),
"DMC:LOGIC_CHNL: DoCreate() - iDmcLogicalDevPtr->GetDynamicDfcQueue()",
KErrNoMemory);
SetDfcQ(iDmcLogicalDevPtr->GetDynamicDfcQueue());
iMsgQ.Receive();
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_CREATE_RETURN,
"DMC:LOGIC_CHNL: DoCreate() # OUT - retVal: %d", retVal);
DMC_TRACE((("DMC:LOGIC_CHNL: DoCreate() # OUT - retVal: %d "), retVal));
return retVal;
}
// ---------------------------------------------------------
// DDmcLogicalChannel::HandleMsg
// ---------------------------------------------------------
void DDmcLogicalChannel::HandleMsg(TMessageBase* aMsg)
{
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_ENTRY,
"DMC:LOGIC_CHNL: HandleMsg() # IN - aMsg: 0x%x",
(TUint)(aMsg));
DMC_TRACE((("DMC:LOGIC_CHNL: HandleMsg() # IN - aMsg: 0x%x "), aMsg));
DMC_TRACE_ASSERT_RESET(aMsg,
"DMC:LOGIC_CHNL: HandleMsg() - aMsg",
KErrNoMemory);
TThreadMessage& m = *reinterpret_cast<TThreadMessage*>(aMsg);
// Get message type
TInt msgId(m.iValue);
OstTrace1(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_1,
"DMC:LOGIC_CHNL: HandleMsg() - msgId: 0x%x",
(TUint)(msgId));
DMC_TRACE((("DMC:LOGIC_CHNL: HandleMsg() - msgId: 0x%x "), msgId));
// close request
if (msgId == static_cast<TInt>(ECloseMsg))
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_3,
"DMC:LOGIC_CHNL: HandleMsg() - ECloseMsg");
DMC_TRACE(("DMC:LOGIC_CHNL: HandleMsg() - ECloseMsg)"));
m.Complete(KErrNone, EFalse);
}
else if (msgId == KMaxTInt)
{
// cancel request
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_4,
"DMC:LOGIC_CHNL: HandleMsg() - KMaxTInt, DoCancel");
DMC_TRACE(("DMC:LOGIC_CHNL: HandleMsg() - KMaxTInt, DoCancel"));
m.Complete(KErrNone, ETrue);
}
else if (msgId >= 0)
{
// sync request
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_5,
"DMC:LOGIC_CHNL: HandleMsg() - DoControl");
DMC_TRACE(("DMC:LOGIC_CHNL: HandleMsg() - DoControl"));
// DoControl
TInt retStatus(DoControl(msgId, m.Ptr0()));
m.Complete(retStatus, ETrue);
}
else
{
// async request
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_6,
"DMC:LOGIC_CHNL: HandleMsg() - DoRequest");
DMC_TRACE(("DMC:LOGIC_CHNL: HandleMsg() - DoRequest"));
// DoRequest
TRequestStatus* usrReqStatPtr = (TRequestStatus *)m.Ptr0();
TInt retStatus(DoRequest(~msgId, usrReqStatPtr, m.Ptr1()));
if (retStatus != KErrNone)
{
Kern::RequestComplete(iClientThreadPtr, usrReqStatPtr, retStatus);
}
m.Complete(KErrNone, ETrue);
}
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_HANDLE_MSG_RETURN,
"DMC:LOGIC_CHNL: HandleMsg() # OUT ");
DMC_TRACE(("DMC:LOGIC_CHNL: HandleMsg() # OUT"));
}
// -----------------------------------------------------------------------------
// DDmcLogicalChannel::SendEvent
// -----------------------------------------------------------------------------
void DDmcLogicalChannel::SendEvent(const RDmc::TEvent& aEvent)
{
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_SEND_EVENT_ENTRY,
"DMC:LOGIC_CHNL: SendEvent() # IN - aEvent: %d", aEvent);
DMC_TRACE((("DMC:LOGIC_CHNL: SendEvent() # IN - aEvent: %d"), aEvent));
// Make sure that a client has subscribed events.
if (iClientStatusPtr)
{
OstTrace1(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_SEND_1,
"DMC:LOGIC_CHNL: SendEvent() - KErrNone: %d", KErrNone);
DMC_TRACE((("DMC:LOGIC_CHNL: SendEvent() - KErrNone: %d"), KErrNone));
TInt retStatus = Kern::ThreadRawWrite(iClientThreadPtr,
iClientEventBufferPtr,
&aEvent,
sizeof(aEvent));
OstTrace1(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_SEND_EVENT_1,
"DMC:LOGIC_CHNL: SendEvent() # IN - retStatus: %d", retStatus);
DMC_TRACE((("DMC:LOGIC_CHNL: SendEvent() # IN - retStatus: %d, iClientStatusPtr: 0x%x"),
retStatus, iClientStatusPtr));
Kern::RequestComplete(iClientThreadPtr, iClientStatusPtr, retStatus);
}
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_SEND_EVENT_RETURN,
"DMC:LOGIC_CHNL: SendEvent() # OUT ");
DMC_TRACE(("DMC:LOGIC_CHNL: SendEvent() # OUT"));
}
// -----------------------------------------------------------------------------
// DDmcLogicalChannel::DoControl
// -----------------------------------------------------------------------------
TInt DDmcLogicalChannel::DoControl(const TInt aFunction, TAny* a1)
{
OstTraceExt2(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_CONTROL_ENTRY,
"DMC:LOGIC_CHNL: DoControl() # IN - aFunction: 0x%x, a1: 0x%x",
(TUint)(aFunction), (TUint)(a1));
DMC_TRACE((("DMC:LOGIC_CHNL: DoControl() # IN - aFunction: 0x%x, a1: 0x%x"), aFunction, a1));
TInt retStatus(KErrBadHandle);
if (iDmcLogicalDevPtr)
{
retStatus = KErrNone;
switch (aFunction)
{
case RDmc::EGetTargetStartUpMode:
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_1,
"DMC:LOGIC_CHNL: DoControl() - EGetTargetStartUpMode");
DMC_TRACE(("DMC:LOGIC_CHNL: DoControl() - EGetTargetStartUpMode"));
RDmc::TTargetStartupMode targetStartUpMode;
retStatus = iDmcLogicalDevPtr->GetTargetStartUpMode(targetStartUpMode);
DMC_TRACE_ASSERT(retStatus == KErrNone);
if (retStatus == KErrNone)
{
retStatus = Kern::ThreadRawWrite(iClientThreadPtr,
a1,
&targetStartUpMode,
sizeof(targetStartUpMode));
OstTraceExt2(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_2,
"DMC:LOGIC_CHNL: DoControl() - retStatus: %d, targetStartUpMode: %d",
retStatus, targetStartUpMode);
DMC_TRACE((("DMC:LOGIC_CHNL: DoControl() - retStatus: %d, targetStartUpMode: %d"),
retStatus, targetStartUpMode));
}
}
break;
case RDmc::EGenerateReset:
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_3,
"DMC:LOGIC_CHNL: DoControl() - EGenerateReset");
DMC_TRACE(("DMC:LOGIC_CHNL: DoControl() - EGenerateReset"));
RDmc::TTargetStartupMode targetStartUpMode;
retStatus = Kern::ThreadRawRead(iClientThreadPtr,
a1,
&targetStartUpMode,
sizeof(targetStartUpMode));
DMC_TRACE_ASSERT(retStatus == KErrNone);
OstTraceExt2(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_4,
"DMC:LOGIC_CHNL: DoControl() - retStatus: %d, targetStartUpMode: %d",
retStatus, targetStartUpMode);
DMC_TRACE((("DMC:LOGIC_CHNL: DoControl() - retStatus: %d, targetStartUpMode: %d"),
retStatus, targetStartUpMode));
if (retStatus == KErrNone)
{
retStatus = iDmcLogicalDevPtr->GenerateReset(targetStartUpMode);
}
DMC_TRACE_ASSERT(retStatus == KErrNone);
}
break;
case RDmc::EPowerOff:
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_5,
"DMC:LOGIC_CHNL: DoControl() - EPowerOff");
DMC_TRACE(("DMC:LOGIC_CHNL: DoControl() - EPowerOff"));
retStatus = iDmcLogicalDevPtr->PowerOff();
DMC_TRACE_ASSERT(retStatus == KErrNone);
}
break;
case RDmc::EIsHiddenReset:
{
OstTrace0(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_6,
"DMC:LOGIC_CHNL: DoControl() - EIsHiddenReset");
DMC_TRACE(("DMC:LOGIC_CHNL: DoControl() - EIsHiddenReset"));
TBool hiddenStatus;
retStatus = iDmcLogicalDevPtr->IsHiddenReset(hiddenStatus);
DMC_TRACE_ASSERT(retStatus == KErrNone);
if (retStatus == KErrNone)
{
retStatus = Kern::ThreadRawWrite(iClientThreadPtr,
a1,
&hiddenStatus,
sizeof(hiddenStatus));
OstTraceExt2(TRACE_FLOW, DDMC_LOGICAL_CHANNEL_DO_CONTROL_7,
"DMC:LOGIC_CHNL: DoControl() - retStatus: %d, hiddenStatus: %d",
retStatus, hiddenStatus);
DMC_TRACE((("DMC:LOGIC_CHNL: DoControl() - retStatus: %d, hiddenStatus: %d"),
retStatus, hiddenStatus));
}
}
break;
default:
{
DMC_TRACE_ALWAYS_ASSERT;
retStatus = KErrNotSupported;
}
break;
}
}
OstTrace1(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_CONTROL_RETURN,
"DMC:LOGIC_CHNL: DoControl() # OUT - retStatus %d:", retStatus);
DMC_TRACE((("DMC:LOGIC_CHNL: DoControl() # OUT - retStatus: %d"), retStatus));
return retStatus;
}
// -----------------------------------------------------------------------------
// DDmcLogicalChannel::DoRequest
// -----------------------------------------------------------------------------
TInt DDmcLogicalChannel::DoRequest(const TInt aReqId, TRequestStatus* const aStatusPtr, TAny* const a1)
{
OstTraceExt3(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_REQUEST_ENTRY,
"DMC:LOGIC_CHNL: DoRequest() # IN - aRegId: 0x%x, aStatusPtr: 0x%x, a1: 0x%x",
(TUint)(aReqId), (TUint)aStatusPtr, (TUint)(a1));
DMC_TRACE((("DMC:LOGIC_CHNL: DoRequest() # IN - aReqId: 0x%x, aStatusPtr: 0x%x, a1: 0x%x"),
aReqId, aStatusPtr, a1));
DMC_TRACE_ASSERT_RESET(a1, "DMC:LOG_DEVICE: DDmcLogicalDevice() - a1", KErrNoMemory);
iClientStatusPtr = aStatusPtr;
iClientEventBufferPtr = static_cast<RDmc::TEvent*>(a1);
iDmcLogicalDevPtr->SubscribeEvents(this);
OstTrace0(TRACE_ENTRY_EXIT, DDMC_LOGICAL_CHANNEL_DO_REQUEST_RETURN,
"DMC:LOGIC_CHNL: DoRequest() # OUT");
DMC_TRACE(("DMC:LOGIC_CHNL: DoRequest() # OUT"));
return KErrNone;
}
// End of File