sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\pccd\d_medch.cpp sl@0: // This LDD allow simulation of media change on a peripheral bus controller. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include "d_medch.h" sl@0: sl@0: const TInt KMajorVersionNumber=1; sl@0: const TInt KMinorVersionNumber=0; sl@0: const TInt KBuildVersionNumber=1; sl@0: sl@0: _LIT(KDFCThreadName,"D_MEDCH_DFC_THREAD"); sl@0: const TInt KMedChThreadPriority = 27; sl@0: sl@0: class DLddFactoryMedCh : public DLogicalDevice sl@0: { sl@0: public: sl@0: DLddFactoryMedCh(); sl@0: virtual TInt Install(); sl@0: virtual void GetCaps(TDes8 &aDes) const; sl@0: virtual TInt Create(DLogicalChannelBase*& aChannel); sl@0: }; sl@0: sl@0: class DLddMedCh : public DLogicalChannel sl@0: { sl@0: public: sl@0: DLddMedCh(); sl@0: ~DLddMedCh(); sl@0: protected: sl@0: virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: virtual void HandleMsg(class TMessageBase *); sl@0: private: sl@0: TInt DoRequest(TInt aReqNo,TAny *a1,TAny *a2); sl@0: TInt DoControl(TInt aFunction,TAny *a1,TAny *a2); sl@0: private: sl@0: static void MsCBFunc(TAny* aPtr); sl@0: private: sl@0: DPBusSocket* iSocketP; sl@0: DThread* iClient; sl@0: TRequestStatus* iReqStat; sl@0: TDynamicDfcQue* iDfcQ; sl@0: sl@0: NTimer iMsCallBack; sl@0: TInt iMsInterval; sl@0: sl@0: DPBusSocket::TPBusSimulateMediaState iDelayedOperation; sl@0: }; sl@0: sl@0: DECLARE_STANDARD_LDD() sl@0: { sl@0: return new DLddFactoryMedCh; sl@0: } sl@0: sl@0: DLddFactoryMedCh::DLddFactoryMedCh() sl@0: /** sl@0: * Constructor sl@0: */ sl@0: { sl@0: sl@0: iParseMask=KDeviceAllowUnit; sl@0: iUnitsMask=0xffffffff; sl@0: iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber); sl@0: } sl@0: sl@0: TInt DLddFactoryMedCh::Install() sl@0: /** sl@0: * Install the device driver. sl@0: */ sl@0: { sl@0: sl@0: TPtrC name = _L("MedCh"); sl@0: return(SetName(&name)); sl@0: } sl@0: sl@0: void DLddFactoryMedCh::GetCaps(TDes8 &aDes) const sl@0: /** sl@0: * Return the media change LDD capabilities. sl@0: */ sl@0: { sl@0: sl@0: TCapsMediaChangeV01 caps; sl@0: caps.version = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber); sl@0: Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps)); sl@0: } sl@0: sl@0: TInt DLddFactoryMedCh::Create(DLogicalChannelBase*& aChannel) sl@0: /** sl@0: * Create a channel on the device. sl@0: */ sl@0: { sl@0: sl@0: aChannel = new DLddMedCh; sl@0: return aChannel ? KErrNone : KErrNoMemory; sl@0: } sl@0: sl@0: DLddMedCh::DLddMedCh() sl@0: /** sl@0: * Constructor sl@0: */ sl@0: : iMsCallBack(MsCBFunc, this) sl@0: { sl@0: sl@0: iClient = &Kern::CurrentThread(); sl@0: ((DObject*)iClient)->Open(); sl@0: } sl@0: sl@0: DLddMedCh::~DLddMedCh() sl@0: /** sl@0: * Destructor sl@0: */ sl@0: { sl@0: if(iSocketP) sl@0: (void)iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)DPBusSocket::EPeriphBusMediaNormal, NULL); sl@0: sl@0: Kern::SafeClose((DObject*&)iClient, NULL); sl@0: sl@0: if (iDfcQ) sl@0: iDfcQ->Destroy(); sl@0: } sl@0: sl@0: TInt DLddMedCh::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer) sl@0: /** sl@0: * Create channel. sl@0: */ sl@0: { sl@0: sl@0: if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer)) sl@0: return(KErrNotSupported); sl@0: sl@0: // sl@0: // Obtain the requested socket (as specified by the opened logical unit) sl@0: // sl@0: iSocketP = DPBusSocket::SocketFromId(aUnit); sl@0: if(iSocketP == NULL) sl@0: return(KErrNoMemory); sl@0: sl@0: if (!iDfcQ) sl@0: { sl@0: TInt r = Kern::DynamicDfcQCreate(iDfcQ, KMedChThreadPriority, KDFCThreadName); sl@0: if (r != KErrNone) sl@0: return r; sl@0: #ifdef CPU_AFFINITY_ANY sl@0: NKern::ThreadSetCpuAffinity((NThread*)(iDfcQ->iThread), KCpuAffinityAny); sl@0: #endif sl@0: sl@0: SetDfcQ(iDfcQ); sl@0: } sl@0: sl@0: iMsgQ.Receive(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DLddMedCh::HandleMsg(TMessageBase* aMsg) sl@0: /** sl@0: * Message Handler sl@0: */ sl@0: { sl@0: sl@0: TThreadMessage& m=*(TThreadMessage*)aMsg; sl@0: TInt id=m.iValue; sl@0: sl@0: if (id == (TInt)ECloseMsg) sl@0: { sl@0: iMsCallBack.Cancel(); sl@0: (void)iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)DPBusSocket::EPeriphBusMediaNormal, NULL); sl@0: m.Complete(KErrNone, EFalse); sl@0: return; sl@0: } sl@0: else if (id == KMaxTInt) sl@0: { sl@0: // DoCancel sl@0: m.Complete(KErrNone, ETrue); sl@0: return; sl@0: } sl@0: sl@0: if (id < 0) sl@0: { sl@0: // DoRequest sl@0: TRequestStatus* pS = (TRequestStatus*)m.Ptr0(); sl@0: iReqStat = pS; sl@0: TInt r = DoRequest(~id, m.Ptr1(), m.Ptr2()); sl@0: if (r != KErrNone) sl@0: Kern::RequestComplete(iClient, pS, r); sl@0: m.Complete(KErrNone, ETrue); sl@0: } sl@0: else sl@0: { sl@0: // DoControl sl@0: TInt r = DoControl(id, m.Ptr0(), m.Ptr1()); sl@0: if(r != KErrCompletion) sl@0: { sl@0: m.Complete(r, ETrue); sl@0: } sl@0: } sl@0: } sl@0: sl@0: TInt DLddMedCh::DoRequest(TInt aFunction, TAny* a1, TAny* a2) sl@0: /** sl@0: * Asynchronous requests sl@0: */ sl@0: { sl@0: sl@0: TInt err = KErrNotSupported; sl@0: sl@0: switch (aFunction) sl@0: { sl@0: case RMedCh::EDelayedDoorOpen: sl@0: { sl@0: const TInt KMsInterval = (TInt)a1; sl@0: iDelayedOperation = DPBusSocket::EPeriphBusDoorOpen; sl@0: err = iMsCallBack.OneShot(NKern::TimerTicks(KMsInterval), ETrue); sl@0: break; sl@0: } sl@0: sl@0: case RMedCh::EDelayedDoorClose: sl@0: { sl@0: const TInt KMsInterval = (TInt)a1; sl@0: const TBool KMediaPresent = (TBool)a2; sl@0: iDelayedOperation = KMediaPresent ? DPBusSocket::EPeriphBusMediaPresent : DPBusSocket::EPeriphBusMediaRemoved; sl@0: err = iMsCallBack.OneShot(NKern::TimerTicks(KMsInterval), ETrue); sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: { sl@0: err = KErrNotSupported; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return err; sl@0: } sl@0: sl@0: TInt DLddMedCh::DoControl(TInt aFunction,TAny* a1, TAny* /*a2*/) sl@0: /** sl@0: * Synchronous requests sl@0: */ sl@0: { sl@0: sl@0: TInt err = KErrNotSupported; sl@0: sl@0: switch (aFunction) sl@0: { sl@0: case RMedCh::EDoorOpen: sl@0: { sl@0: err = iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)DPBusSocket::EPeriphBusDoorOpen, NULL); sl@0: break; sl@0: } sl@0: sl@0: case RMedCh::EDoorClose: sl@0: { sl@0: const TBool KMediaPresent = (TBool)a1; sl@0: sl@0: err = iSocketP->ControlIO(DPBusSocket::EControlMediaState, sl@0: (TAny*)(KMediaPresent ? DPBusSocket::EPeriphBusMediaPresent : DPBusSocket::EPeriphBusMediaRemoved), sl@0: NULL); sl@0: break; sl@0: } sl@0: sl@0: case RMedCh::EDoorNormal: sl@0: { sl@0: err = iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)DPBusSocket::EPeriphBusMediaNormal, NULL); sl@0: break; sl@0: } sl@0: sl@0: case RMedCh::EDoubleDoorOpen: sl@0: { sl@0: err = iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)DPBusSocket::EPeriphBusMediaDoubleDoorOpen, NULL); sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: { sl@0: err = KErrNotSupported; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return err; sl@0: } sl@0: sl@0: void DLddMedCh::MsCBFunc(TAny* aPtr) sl@0: /** sl@0: * Delayed Open/Close timer callback sl@0: */ sl@0: { sl@0: DLddMedCh& mcldd=*(DLddMedCh*)aPtr; sl@0: TInt err = mcldd.iSocketP->ControlIO(DPBusSocket::EControlMediaState, (TAny*)mcldd.iDelayedOperation, NULL); sl@0: Kern::RequestComplete(mcldd.iClient, mcldd.iReqStat, err); sl@0: } sl@0: