# HG changeset patch # User William Roberts # Date 1267298284 0 # Node ID 72a7468afdd48d37a997ec8ab3f18d0aae4e5a35 # Parent 50cddb1eb3af8f83f2ad6b2d4c36d313de26e613# Parent a65b6baedd2efeee660b2f2c17805a7d057e24b0 Merge in tip of phonesim-integ branch, to get svpframebuffer and some other stuff? diff -r 50cddb1eb3af -r 72a7468afdd4 baseport/syborg/bld.inf --- a/baseport/syborg/bld.inf Fri Jan 08 12:04:26 2010 +0000 +++ b/baseport/syborg/bld.inf Sat Feb 27 19:18:04 2010 +0000 @@ -85,6 +85,8 @@ svpsnapdriver/svpsnapdriver svpsnapdriver/snapapp +//NGA framebuffer +svpframebuffer/svpframebuffer //Add Sound Driver soundsc\soundsc diff -r 50cddb1eb3af -r 72a7468afdd4 baseport/syborg/svpframebuffer/svpframebuffer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/baseport/syborg/svpframebuffer/svpframebuffer.cpp Sat Feb 27 19:18:04 2010 +0000 @@ -0,0 +1,1055 @@ +/* +* 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: Minimalistic frame buffer driver +* +*/ +#include +#include "platform.h" +#include +#include +#include +#include + +#include +#include "svpframebuffer.h" + +DLcdPowerHandler * DLcdPowerHandler::pLcd = NULL; + +TPhysAddr Syborg::VideoRamPhys; +TPhysAddr Syborg::VideoRamPhysSecure; // Secure display memory + +TPhysAddr TSyborg::VideoRamPhys() +{ + __KTRACE_OPT(KEXTENSION,Kern::Printf("TSyborg::VideoRamPhys: VideoRamPhys=0x%x", Syborg::VideoRamPhys)); + return Syborg::VideoRamPhys; +} + +TPhysAddr TSyborg::VideoRamPhysSecure() +{ + return Syborg::VideoRamPhysSecure; +} + +LOCAL_C TInt DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) +{ + DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr; + return pH->HalFunction(aFunction,a1,a2); +} + +static void rxMsg(TAny* aPtr) +{ + DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr; + TMessageBase* pM = h.iMsgQ.iMessage; + if(pM) + h.HandleMsg(pM); +} + +static void power_up_dfc(TAny* aPtr) +{ + ((DLcdPowerHandler*)aPtr)->PowerUpDfc(); +} + +void power_down_dfc(TAny* aPtr) +{ + ((DLcdPowerHandler*)aPtr)->PowerDownDfc(); +} + +void DLcdPowerHandler::DisplayOn() +{ + PowerUpLcd(iSecureDisplay); + iDisplayOn = ETrue; +} + +void DLcdPowerHandler::DisplayOff() +{ + PowerDownLcd(); + iDisplayOn = EFalse; +} + +void DLcdPowerHandler::SwitchDisplay(TBool aSecure) + { + if(aSecure) + { + if(!iSecureDisplay) + { + DisplayOff(); + iSecureDisplay = ETrue; + DisplayOn(); + } + } + else + { + if(iSecureDisplay) + { + DisplayOff(); + iSecureDisplay = EFalse; + DisplayOn(); + } + } + } + +void DLcdPowerHandler::PowerUpDfc() +{ + DisplayOn(); + PowerUpDone(); +} + +void DLcdPowerHandler::PowerDownDfc() +{ + DisplayOff(); + PowerDownDone(); +} + +void DLcdPowerHandler::PowerDown(TPowerState) +{ + iPowerDownDfc.Enque(); +} + +void DLcdPowerHandler::PowerUp() +{ + iPowerUpDfc.Enque(); +} + +void DLcdPowerHandler::PowerUpLcd(TBool aSecure) +{ +#if 1 + WriteReg(iPortAddr, FB_ENABLED, 0); + WriteReg(iPortAddr, FB_BASE, aSecure ? iSecurevRamPhys : ivRamPhys); + WriteReg(iPortAddr, FB_WIDTH, iVideoInfo.iSizeInPixels.iWidth); + WriteReg(iPortAddr, FB_BLANK, 0); + WriteReg(iPortAddr, FB_BPP, 32); + WriteReg(iPortAddr, FB_COLOR_ORDER, 0); + WriteReg(iPortAddr, FB_BYTE_ORDER, 0); + WriteReg(iPortAddr, FB_PIXEL_ORDER, 0); + WriteReg(iPortAddr, FB_INT_MASK, 0); + WriteReg(iPortAddr, FB_ENABLED, 1); + WriteReg(iPortAddr, FB_HEIGHT, iVideoInfo.iSizeInPixels.iHeight); +#endif +} + +void DLcdPowerHandler::PowerDownLcd() +{ + WriteReg(iPortAddr, FB_BLANK, 1); +} + +DLcdPowerHandler::DLcdPowerHandler() + : DPowerHandler(KLitLcd), + iMsgQ(rxMsg,this,NULL,1), + iPowerUpDfc(&power_up_dfc,this,6), + iPowerDownDfc(&power_down_dfc,this,7) +{ +} + +void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo) +{ + anInfo.iWindowHandleValid = EFalse; + anInfo.iWindowHandle = NULL; + anInfo.iScreenAddressValid = ETrue; + anInfo.iScreenAddress = (TAny *)(iChunk->LinearAddress()); + anInfo.iScreenSize.iWidth = iVideoInfo.iSizeInPixels.iWidth; + anInfo.iScreenSize.iHeight = iVideoInfo.iSizeInPixels.iHeight; +} + +void DLcdPowerHandler::HandleMsg(TMessageBase* aMsg) +{ + if(aMsg->iValue) + DisplayOn(); + else + DisplayOff(); + aMsg->Complete(KErrNone,ETrue); +} + +void DLcdPowerHandler::WsSwitchOnScreen() +{ + TThreadMessage& m = Kern::Message(); + m.iValue = ETrue; + m.SendReceive(&iMsgQ); +} + +void DLcdPowerHandler::WsSwitchOffScreen() +{ + TThreadMessage& m = Kern::Message(); + m.iValue = EFalse; + m.SendReceive(&iMsgQ); +} + +TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure) +{ + NKern::FMWait(&iLock); + if(aSecure) + aInfo = iSecureVideoInfo; + else + aInfo = iVideoInfo; + NKern::FMSignal(&iLock); + return KErrNone; +} + +TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo) +{ + if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes) + return KErrArgument; + + NKern::FMWait(&iLock); + aInfo = iVideoInfo; + NKern::FMSignal(&iLock); + + if(aMode != aInfo.iDisplayMode) + { + aInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; + aInfo.iIsPalettized = KConfigIsPalettized; + aInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; + aInfo.iBitsPerPixel = KConfigBitsPerPixel; + } + return KErrNone; +} + +TInt DLcdPowerHandler::AllocateFrameBuffer() +{ + // Allocate physical RAM for video + TInt vSize = TSyborg::VideoRamSize(); + + NKern::ThreadEnterCS(); + TInt r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhys); + if (r != KErrNone) + { + NKern::ThreadLeaveCS(); + Kern::Fault("AllocVideoRam",r); + } + + // Map the video RAM + ivRamPhys = TSyborg::VideoRamPhys(); + + r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); + + NKern::ThreadLeaveCS(); + + if(r != KErrNone) + return r; + + TUint* pV = (TUint*)iChunk->LinearAddress(); + + // Allocate physical RAM for secure display + NKern::ThreadEnterCS(); + r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhysSecure); + if (r != KErrNone) + { + NKern::ThreadLeaveCS(); + Kern::Fault("AllocVideoRam 2",r); + } + iSecurevRamPhys = ivRamPhys + vSize; + TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC); + + NKern::ThreadLeaveCS(); + + if(r2 != KErrNone) + return r2; + + TUint* pV2 = (TUint*)iSecureChunk->LinearAddress(); + + iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; + iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; + iVideoInfo.iDisplayMode = KConfigLcdDisplayMode; + iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; + iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; + iVideoInfo.iIsPalettized = KConfigIsPalettized; + iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel; + iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; + iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; + iVideoInfo.iIsMono = KConfigIsMono; + iVideoInfo.iVideoAddress = (TInt)pV; + iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape; + iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB; + + iSecureVideoInfo = iVideoInfo; + iSecureVideoInfo.iVideoAddress = (TInt)pV2; + + // Alloc Physical RAM for the Composition Buffers used by the GCE + iSize = 4*480*640;//FRAME_BUFFER_SIZE( iVideoInfo.iBitsPerPixel, iVideoInfo.iSizeInPixels.iWidth, iVideoInfo.iSizeInPixels.iHeight); + __GCE_DEBUG_PRINT2("DLcdPowerHandler.iSize = %d\n", iSize ); + // double and round the page size + TUint round = 2*Kern::RoundToPageSize(iSize); + + r=Epoc::AllocPhysicalRam(round , iCompositionPhysical); + if(r!=KErrNone) + { + return r; + } + + return KErrNone; +} + + +TInt DLcdPowerHandler::SetDisplayMode(TInt aMode) +{ + if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes) + return KErrArgument; + + // store the current mode + iVideoInfo.iDisplayMode = aMode; + + // store the current mode for secure screen + iSecureVideoInfo.iDisplayMode = aMode; + + return KErrNone; +} + +TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2) +{ + TInt r=KErrNone; + switch(aFunction) + { + case EDisplayHalScreenInfo: + { + TPckgBuf vPckg; + ScreenInfo(vPckg()); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + break; + } + case EDisplayHalWsRegisterSwitchOnScreenHandling: + { + iWsSwitchOnScreen=(TBool)a1; + break; + } + case EDisplayHalWsSwitchOnScreen: + { + WsSwitchOnScreen(); + break; + } + case EDisplayHalModeCount: + { + TInt ndm = KConfigLcdNumberOfDisplayModes; + kumemput32(a1, &ndm, sizeof(ndm)); + break; + } + case EDisplayHalSetMode: + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("EDisplayHalSetMode")); + __SECURE_KERNEL( + if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode"))) + return KErrPermissionDenied; + ) + r = SetDisplayMode((TInt)a1); + break; + } + case EDisplayHalMode: + { + kumemput32(a1, &iVideoInfo.iDisplayMode, sizeof(iVideoInfo.iDisplayMode)); + r = KErrNone; + break; + } + case EDisplayHalSetPaletteEntry: + { + __SECURE_KERNEL( + if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry"))) + return KErrPermissionDenied; + ) + r = KErrNotSupported; + break; + } + case EDisplayHalPaletteEntry: + { + TInt entry; + kumemget32(&entry, a1, sizeof(TInt)); + r = KErrNotSupported; + break; + } + case EDisplayHalSetState: + { + __SECURE_KERNEL( + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState"))) + return KErrPermissionDenied; + ) + if((TBool)a1) + WsSwitchOnScreen(); + else + WsSwitchOffScreen(); + break; + } + case EDisplayHalState: + { + kumemput32(a1, &iDisplayOn, sizeof(TBool)); + break; + } + case EDisplayHalColors: + { + TInt mdc = 1<<24; + kumemput32(a1, &mdc, sizeof(mdc)); + break; + } + case EDisplayHalCurrentModeInfo: + { + TPckgBuf vPckg; + r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2); + if(KErrNone == r) + Kern::InfoCopy(*(TDes8*)a1,vPckg); + break; + } + case EDisplayHalSpecifiedModeInfo: + { + TPckgBuf vPckg; + TInt mode; + kumemget32(&mode, a1, sizeof(mode)); + r = GetSpecifiedDisplayModeInfo(mode, vPckg()); + if(KErrNone == r) + Kern::InfoCopy(*(TDes8*)a2,vPckg); + break; + } + case EDisplayHalSecure: + { + kumemput32(a1, &iSecureDisplay, sizeof(TBool)); + break; + } + case EDisplayHalSetSecure: + { + __SECURE_KERNEL( + if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure"))) + return KErrPermissionDenied; + ) + SwitchDisplay((TBool)a1); + break; + } + default: + { + r = KErrNotSupported; + break; + } + } + return r; +} + +TInt DLcdPowerHandler::Create() +{ + __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create") ); + pLcd = this; + + iPortAddr = KHwBaseClcd; + + iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth; + iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight; + iVideoInfo.iDisplayMode = KConfigLcdDisplayMode; + iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel; + iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines; + iVideoInfo.iIsPalettized = KConfigIsPalettized; + iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel; + iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips; + iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips; + iVideoInfo.iIsMono = KConfigIsMono; + // !@! iVideoInfo.iVideoAddress = (TInt)pV; + iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape; + iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB; + + iSecureVideoInfo = iVideoInfo; + // !@! iSecureVideoInfo.iVideoAddress = (TInt)pV2; + + TInt r = AllocateFrameBuffer(); + if(r == KErrNone) + { + r = Kern::AddHalEntry(EHalGroupDisplay,DoHalFunction,this); + } + + if(r != KErrNone) + { + __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create failed %d", r) ); + return r; + } + + iPowerUpDfc.SetDfcQ(iDfcQ); + iPowerDownDfc.SetDfcQ(iDfcQ); + iMsgQ.SetDfcQ(iDfcQ); + iMsgQ.Receive(); + + Add(); + DisplayOn(); + + return KErrNone; +} + +/** + * Register the call back function. + * Components interested in receiving notification of the Vsync interrupt should register a callback function. + */ +EXPORT_C TInt DLcdPowerHandler::RegisterCallback(TLcdUserCallBack* aCbPtr) +{ + __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::RegisterCallBack %08x\n",aCbPtr->iCbFn) ); + + TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock); + + if(aCbPtr != NULL) + { + if ( pLcd->iAppCallBk[0] == NULL ) + { + pLcd->iAppCallBk[0] = aCbPtr; + } + else + { + if((pLcd->iAppCallBk[1] == NULL) && (pLcd->iAppCallBk[0]->iCbFn != aCbPtr->iCbFn)) + { + pLcd->iAppCallBk[1] = aCbPtr; + } + else + { + __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); + return KErrInUse; + } + } + + __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); + __KTRACE_OPT(KEXTENSION ,Kern::Printf("iCbFn) ); + return KErrNone; + } + else + { + __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); + __KTRACE_OPT(KEXTENSION, Kern::Printf("Error: The supplied listener's callback is NULL")); + return KErrArgument; + } +} + + +/** + *DeRegister the call back function + */ +EXPORT_C void DLcdPowerHandler::DeRegisterCallback(TLcdUserCallBack* aCbPtr) +{ + __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn) ); + + TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock); + if(aCbPtr != NULL) + { + if( pLcd->iAppCallBk[0] != NULL) + { + if ( (pLcd->iAppCallBk[0]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[0]->iCbFn == aCbPtr->iCbFn) ) + { + pLcd->iAppCallBk[0] = NULL; + } + } + + if( pLcd->iAppCallBk[1] != NULL) + { + if ( (pLcd->iAppCallBk[1]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[1]->iCbFn == aCbPtr->iCbFn) ) + { + pLcd->iAppCallBk[1] = NULL; + } + } + } + __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq); + __KTRACE_OPT(KEXTENSION ,Kern::Printf("iCbFn) ); +} + +/** + Constructor +*/ +DDisplayPddSyborg::DDisplayPddSyborg(): + iPendingBuffer(NULL), + iActiveBuffer(NULL), + iChunk(NULL), + iLcdCallback(NULL), + iVSyncDfc(&VSyncDfcFn, this, KVSyncDfcPriority) + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::DDisplayPddSyborg\n"); + + iPostFlag = EFalse; + } + +/** + Destructor +*/ +DDisplayPddSyborg::~DDisplayPddSyborg() + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::~DDisplayPddSyborg() \n"); + + if(iLcdCallback) + { + DLcdPowerHandler::pLcd->DeRegisterCallback(iLcdCallback) ; + delete iLcdCallback; + iLcdCallback = NULL; + } + + //The DFC Queue is owned by DLcdPowerHandler so we shouldn't call Destroy() at this point. + if (iDfcQ) + { + iDfcQ=NULL; + } + + DChunk* chunk = (DChunk*) __e32_atomic_swp_ord_ptr(&iChunk, 0); + + if(chunk) + { + Kern::ChunkClose(chunk); + } + + } + +/** + Set the Legacy Mode by setting the appropriate Frame control value. + +*/ +TInt DDisplayPddSyborg::SetLegacyMode() + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetLegacyMode()\n"); + + return KErrNone; + } + +/** + Set the GCE mode by posting a composition buffer. + +*/ +TInt DDisplayPddSyborg::SetGceMode() + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetGceMode()\n"); + + PostCompositionBuffer(&iLdd->iCompositionBuffer[0]); + return KErrNone; + } + +/** + @param aDegOfRot The requested rotation + @return KErrNone +*/ +TInt DDisplayPddSyborg::SetRotation(TInt aDegOfRot) + { + return KErrNone; + } + +/** + Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization + with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to + be posted next. Layer 3 is associated with user buffers. + + @param aNode Pointer to the User buffer to post. +*/ +TInt DDisplayPddSyborg::PostUserBuffer(TBufferNode* aNode) + { + + __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostUserBuffer : aNode->iAddress = %08x\n", aNode->iAddress); + + if(iPendingBuffer) + { + iPendingBuffer->iState = EBufferFree; + if (!(iPendingBuffer->iType == EBufferTypeUser) ) + { + iPendingBuffer->iFree = ETrue; + } + } + + aNode->iState = EBufferPending; + iPendingBuffer = aNode; + iPostFlag = ETrue; + + // Activate the posted buffer + TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress ); + WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress ); + /* Queue a DFC to complete the request*/ + iVSyncDfc.Enque(); + + return KErrNone; + } + +/** + Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization + with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to + be posted next. Layer 1 and 2 are associated with composition buffers 0 and 1 respectively. + + @param aNode Pointer to the Composition buffer to post. +*/ +TInt DDisplayPddSyborg::PostCompositionBuffer(TBufferNode* aNode) + { + + __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostCompositionBuffer : aNode->iAddress = %08x\n", aNode->iAddress); + + if(iPendingBuffer) + { + iPendingBuffer->iState = EBufferFree; + if (iPendingBuffer->iType == EBufferTypeUser) + { + RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel); + } + else + { + iPendingBuffer->iFree = ETrue; + } + } + aNode->iState = EBufferPending; + aNode->iFree = EFalse; + iPendingBuffer = aNode; + iPostFlag = ETrue; + + // Activate the posted buffer + TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress ); + WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress ); + + /* Queue a DFC to complete the request*/ + iVSyncDfc.Enque(); + + return KErrNone; + } + +/** + Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization + with V Sync so it will take affect in the next V Sync after that) and also set the Legacy Buffer as the buffer to + be posted next.Layer 0 is associated with legacy buffer. + + @param aNode Pointer to the Composition buffer to post. +*/ +TInt DDisplayPddSyborg::PostLegacyBuffer() + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::PostLegacyBuffer() \n"); + + if(iPendingBuffer) + { + iPendingBuffer->iState = EBufferFree; + if (iPendingBuffer->iType == EBufferTypeUser) + { + + RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel); + } + else + { + iPendingBuffer->iFree = ETrue; + } + } + + + iLdd->iLegacyBuffer[0].iState = EBufferPending; + iLdd->iLegacyBuffer[0].iFree = EFalse; + iPendingBuffer = &iLdd->iLegacyBuffer[0]; + iPostFlag = ETrue; + + // Activate the posted buffer + WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, TSyborg::VideoRamPhys() ); + + /* Queue a DFC to complete the request*/ + iVSyncDfc.Enque(); + + return KErrNone; + } + +/** + Handles device specific operations when a close message has been sent to the Logical Channel. + +*/ +TInt DDisplayPddSyborg::CloseMsg() + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::CloseMsg()\n"); + + iPendingBuffer = NULL; + iActiveBuffer = NULL; + + iVSyncDfc.Cancel(); + return KErrNone; + } + +/** + Called by the LDD's DoCreate function to handle the device specific part of opening the channel. + (DoCreate is called by RDisplayChannel::Open) + + @param aUnit The screen unit + + @return KErrNone if successful; or one of the other system wide error codes. +*/ +TInt DDisplayPddSyborg::CreateChannelSetup(TInt aUnit) + { + __GCE_DEBUG_PRINT("DDisplayPddSyborg::CreateChannelSetup\n"); + + iScreenInfo = DLcdPowerHandler::pLcd->iVideoInfo; + iLdd->iUnit = aUnit; + + iLdd->iDisplayInfo.iAvailableRotations = RDisplayChannel::ERotationNormal; + iLdd->iDisplayInfo.iNormal.iOffsetBetweenLines = iScreenInfo.iOffsetBetweenLines; + iLdd->iDisplayInfo.iNormal.iHeight = iScreenInfo.iSizeInPixels.iHeight; + iLdd->iDisplayInfo.iNormal.iWidth = iScreenInfo.iSizeInPixels.iWidth; + iLdd->iDisplayInfo.iNumCompositionBuffers = KDisplayCBMax; + iLdd->iDisplayInfo.iBitsPerPixel = iScreenInfo.iBitsPerPixel; + iLdd->iDisplayInfo.iRefreshRateHz = 60; + + + switch (iScreenInfo.iBitsPerPixel) + { + case 16: + iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_565; + break; + case 24: + iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_888; + break; + case 32: + iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatARGB_8888; + break; + default: + iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatUnknown; + break; + } + + iLdd->iCurrentRotation = RDisplayChannel::ERotationNormal; + + // Open shared chunk to the composition framebuffer + + DChunk* chunk = 0; + TLinAddr chunkKernelAddr = 0; + TUint32 chunkMapAttr = 0; + + // round to twice the page size + TUint round = 2*Kern::RoundToPageSize(DLcdPowerHandler::pLcd->iSize); + + __GCE_DEBUG_PRINT2("DDisplayPddSyborg::CreateChannelSetup DLcdPowerHandler::pLcd->iSize = %d\n", DLcdPowerHandler::pLcd->iSize ); + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = round; + info.iMapAttr = EMapAttrFullyBlocking; + info.iOwnsMemory = EFalse; + info.iDestroyedDfc = 0; + + TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); + + __GCE_DEBUG_PRINT2("CreateChannelSetup:ChunkCreate called for composition chunk. Set iChunkKernelAddr = %08x\n", chunkKernelAddr ); + + if( r == KErrNone) + { + // map our chunk + r = Kern::ChunkCommitPhysical(chunk, 0,round , DLcdPowerHandler::pLcd->iCompositionPhysical); + __GCE_DEBUG_PRINT2("Mapping chunk %d", r); + if(r != KErrNone) + { + Kern::ChunkClose(chunk); + } + } + + if ( r!= KErrNone) + { + return r; + } + + iChunk = chunk; + + // init CB 0 + iLdd->iCompositionBuffer[0].iType = EBufferTypeComposition; + iLdd->iCompositionBuffer[0].iBufferId = 0; + iLdd->iCompositionBuffer[0].iFree = ETrue; + iLdd->iCompositionBuffer[0].iState = EBufferFree; + iLdd->iCompositionBuffer[0].iAddress = chunkKernelAddr; + iLdd->iCompositionBuffer[0].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr); + iLdd->iCompositionBuffer[0].iChunk = chunk; + iLdd->iCompositionBuffer[0].iHandle = 0; + iLdd->iCompositionBuffer[0].iOffset = 0; + iLdd->iCompositionBuffer[0].iSize = DLcdPowerHandler::pLcd->iSize; + iLdd->iCompositionBuffer[0].iPendingRequest = 0; + + // init CB 1 + iLdd->iCompositionBuffer[1].iType = EBufferTypeComposition; + iLdd->iCompositionBuffer[1].iBufferId = 1; + iLdd->iCompositionBuffer[1].iFree = ETrue; + iLdd->iCompositionBuffer[1].iState = EBufferFree; + iLdd->iCompositionBuffer[1].iAddress = chunkKernelAddr + DLcdPowerHandler::pLcd->iSize; + iLdd->iCompositionBuffer[1].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr + DLcdPowerHandler::pLcd->iSize); + iLdd->iCompositionBuffer[1].iChunk = chunk; + iLdd->iCompositionBuffer[1].iHandle = 0; + iLdd->iCompositionBuffer[1].iOffset = DLcdPowerHandler::pLcd->iSize; + iLdd->iCompositionBuffer[1].iSize = DLcdPowerHandler::pLcd->iSize; + iLdd->iCompositionBuffer[1].iPendingRequest = 0; + + iLdd->iCompositionBuffIdx = 0; + //Use the same DFC queue created by the DLcdPowerHandler so all hardware accesses are executed under the same DFC thread. + iDfcQ= DLcdPowerHandler::pLcd->iDfcQ; + + // Set the Post DFC. + iVSyncDfc.SetDfcQ(iDfcQ); + + + return KErrNone; + } + +/** +Detect whether a post operation is pending +*/ +TBool DDisplayPddSyborg::PostPending() + { + return (iPendingBuffer != NULL); + } + +/** + Return the DFC queue to be used for this device. + */ +TDfcQue * DDisplayPddSyborg::DfcQ(TInt aUnit) + { + return iDfcQ; + } + +void DDisplayPddSyborg::VSyncDfcFn(TAny* aChannel) + { + DDisplayPddSyborg * channel =(DDisplayPddSyborg*)aChannel; + + if (channel->iPostFlag) + { + channel->iPostFlag = EFalse; + + if (channel->iActiveBuffer) + { + //When a User buffer is registered its iFree member becomes EFalse and Deregister sets it + //back to ETrue. Composition and Legacy buffers are not free when they are in the pending or + //active state. + if (channel->iActiveBuffer->iType == EBufferTypeUser) + { + channel->RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrNone); + } + else + { + channel->iActiveBuffer->iFree = ETrue; + } + + channel->iActiveBuffer->iState = EBufferFree; + + + //If no buffer was available during a call to GetCompositionBuffer the active buffer has + //been returned as the next available one, so we must set the buffer to the proper state before we + //send the notification. + if(channel->iLdd->iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus) + { + channel->iActiveBuffer->iState = EBufferCompose; + channel->RequestComplete(RDisplayChannel::EReqGetCompositionBuffer, KErrNone); + + } + + channel->iActiveBuffer = NULL; + } + + if (channel->iPendingBuffer) + { + __GCE_DEBUG_PRINT2("DDisplayPddSyborg::VSyncDfcFn moving pending buffer at address %08x to the active state\n", channel->iPendingBuffer->iAddress); + channel->iActiveBuffer = channel->iPendingBuffer; + channel->iActiveBuffer->iState = EBufferActive; + channel->iPendingBuffer = NULL; + + channel->RequestComplete(RDisplayChannel::EReqWaitForPost, KErrNone); + } + } + } +//***************************************************************** +//DDisplayPddFactory +//*****************************************************************/ + + +/** + Constructor +*/ +DDisplayPddFactory::DDisplayPddFactory() + { + __GCE_DEBUG_PRINT("DDisplayPddFactory::DDisplayPddFactory()\n"); + + iVersion = TVersion(KDisplayChMajorVersionNumber, + KDisplayChMinorVersionNumber, + KDisplayChBuildVersionNumber); + } + +/** + PDD factory function. Creates a PDD object. + + @param aChannel A pointer to an PDD channel object which will be initialised on return. + + @return KErrNone if object successfully allocated, KErrNoMemory if not. +*/ +TInt DDisplayPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer) + { + DDisplayPddSyborg *device= new DDisplayPddSyborg() ; + aChannel=device; + if (!device) + { + return KErrNoMemory; + } + return KErrNone; + } + + +/** + Set the Pdd name and return error code +*/ +TInt DDisplayPddFactory::Install() + { + __GCE_DEBUG_PRINT("DDisplayPddFactory::Install() \n"); + + TBuf<32> name(RDisplayChannel::Name()); + _LIT(KPddExtension,".pdd"); + name.Append(KPddExtension); + return SetName(&name); + } + + +void DDisplayPddFactory::GetCaps(TDes8& /*aDes*/) const + { + //Not supported + } + + +/** + Validate version and number of units. +*/ +TInt DDisplayPddFactory::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer) + { + if (!Kern::QueryVersionSupported(iVersion,aVer)) + { + return KErrNotSupported; + } + + if (aUnit != 0) + { + return KErrNotSupported; + } + + return KErrNone; + } + +DECLARE_EXTENSION_PDD() +/** + "Standard PDD" entrypoint.Creates PDD factory when Kern::InstallPhysicalDevice is called + + @return pointer to the PDD factory object. +*/ + { + __GCE_DEBUG_PRINT("DECLARE_EXTENSION_PDD()\n"); + return new DDisplayPddFactory ; + } + + +DECLARE_STANDARD_EXTENSION() +{ + TInt r = KErrNoMemory; + DLcdPowerHandler* pH=new DLcdPowerHandler; + if(pH) + { + r = pH->Create(); + if ( r == KErrNone) + { + pH->iDfcQ = Kern::DfcQue0(); // use low priority DFC queue for this driver + + DDisplayPddFactory * device = new DDisplayPddFactory; + + if (device==NULL) + { + r=KErrNoMemory; + } + else + { + r=Kern::InstallPhysicalDevice(device); + } + + #ifdef CPU_AFFINITY_ANY + NKern::ThreadSetCpuAffinity((NThread*) pH->iDfcQ->iThread, KCpuAffinityAny); + #endif + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Installing the display device from the kernel extension returned with error code %d",r)); + + } + } + + return r; +} diff -r 50cddb1eb3af -r 72a7468afdd4 baseport/syborg/svpframebuffer/svpframebuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/baseport/syborg/svpframebuffer/svpframebuffer.h Sat Feb 27 19:18:04 2010 +0000 @@ -0,0 +1,297 @@ +/* +* 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: Minimalistic frame buffer driver +* +*/ + +#ifndef _SVPFRAMEBUFFER_H +#define _SVPFRAMEBUFFER_H + +#include + +#include +#include + +#define __SVPFRAMEBUFFER_DEBUG + +#ifdef __SVPFRAMEBUFFER_DEBUG + +#define __GCE_DEBUG_PRINT(a) Kern::Printf(a) +#define __GCE_DEBUG_PRINT2(a,b) Kern::Printf(a,b) + +#else + +#define __GCE_DEBUG_PRINT(a) +#define __GCE_DEBUG_PRINT2(a,b) + +#endif + +// Macro to calculate the screen buffer size +// aBpp is the number of bits-per-pixel, aPpl is the number of pixels per line and aLpp number of lines per panel +#define FRAME_BUFFER_SIZE(aBpp,aPpl,aLpp) ((aBpp/8)*aPpl*aLpp) + +_LIT(KLitLcd,"SYBORG_FB"); + +const TUint KConfigLcdWidth = 640; +const TUint KConfigLcdHeight = 480; +const TInt KConfigLcdWidthInTwips = 9638; +const TInt KConfigLcdHeightInTwips = 7370; +const TBool KConfigIsMono = 0; +const TBool KConfigIsPalettized = 0; +const TInt KCOnfigOffsetToFirstPixel = 0; +const TBool KConfigPixelOrderRGB = 0; +const TBool KConfigPixelOrderLandscape = 1; +const TInt KConfigLcdDisplayMode = 2; +//const TInt KConfigLcdDisplayMode = 1; +const TInt KConfigLcdNumberOfDisplayModes = 3; + + +const TInt KConfigBitsPerPixel = 24; +const TInt KCOnfigOffsetBetweenLines = 2560; + +const TInt KVSyncDfcPriority = 7 ; //priority of DFC within the queue (0 to 7, where 7 is highest) + +/********************************************************************/ +/* Class Definition */ +/********************************************************************/ +/** + * This class defines a callback mechanism that is used by a resource user to specify its callback. It contains a + * function pointer and data pointer. The function pointer specifies the user callback function to be invoked by the + * resource while the data pointer specifies the data to be passed to the callback function. + */ +class TLcdUserCallBack + { +public: + // The constructor for the callback mechanism. + TLcdUserCallBack(TInt (*aFunction)(TUint aResID, TAny* aPtr), TAny* aPtr) + + { + iCbFn = aFunction; + iDataPtr = aPtr; + } + +public: + // The callback function pointer. + TInt (*iCbFn)(TUint aResID, TAny* aPtr); + + // Pointer to the data structure to be passed to the callback function. + TAny *iDataPtr; + }; + +class DLcdPowerHandler : public DPowerHandler +{ +public: // from DPowerHandler + void PowerDown(TPowerState); + void PowerUp(); +public: // to prevent a race condition with WServer trying to power up/down at the same time + void PowerUpDfc(); + void PowerDownDfc(); +public: + DLcdPowerHandler(); + TInt Create(); + void DisplayOn(); + void DisplayOff(); + TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2); + + void PowerUpLcd(TBool aSecure); + void PowerDownLcd(); + + void ScreenInfo(TScreenInfoV01& aInfo); + void WsSwitchOnScreen(); + void WsSwitchOffScreen(); + void HandleMsg(TMessageBase* aMsg); + void SwitchDisplay(TBool aSecure); + +private: + TInt GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure); + TInt GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo); + TInt SetDisplayMode(TInt aMode); + TInt AllocateFrameBuffer(); + +public: + IMPORT_C static TInt RegisterCallback(TLcdUserCallBack* aCbPtr); + IMPORT_C static void DeRegisterCallback(TLcdUserCallBack* aCbPtr); + +private: + TBool iDisplayOn; + DPlatChunkHw* iChunk; + DPlatChunkHw* iSecureChunk; + TBool iWsSwitchOnScreen; + TBool iSecureDisplay; + +public: + TDfcQue* iDfcQ; + TMessageQue iMsgQ; // to prevent a race condition with Power Manager trying to power up/down at the same time + TDfc iPowerUpDfc; + TDfc iPowerDownDfc; + +private: + NFastMutex iLock; + TPhysAddr ivRamPhys; + TPhysAddr iSecurevRamPhys; + TLcdUserCallBack * iAppCallBk[2]; + +public: + TVideoInfoV01 iVideoInfo; + TVideoInfoV01 iSecureVideoInfo; + TInt iSize; + TLinAddr iPortAddr; + TPhysAddr iCompositionPhysical; + static DLcdPowerHandler * pLcd; + +enum { + FB_ID = 0, + FB_BASE = 1, + FB_HEIGHT = 2, + FB_WIDTH = 3, + FB_ORIENTATION = 4, + FB_BLANK = 5, + FB_INT_MASK = 6, + /* begin new interface */ + FB_INTERRUPT_CAUSE = 7, + FB_BPP = 8, + FB_COLOR_ORDER = 9, + FB_BYTE_ORDER = 10, + FB_PIXEL_ORDER = 11, + FB_ROW_PITCH = 12, + FB_ENABLED = 13, + FB_PALETTE_START = 0x400 >> 2, + FB_PALETTE_END = FB_PALETTE_START+256-1, + /* end new interface */ + }; + +#define FB_INT_VSYNC (1U << 0) +#define FB_INT_BASE_UPDATE_DONE (1U << 1) + +}; + +class DDisplayPddSyborg : public DDisplayPdd + { + + public: + DDisplayPddSyborg(); + ~DDisplayPddSyborg(); + + /** + Called by the LDD to handle the device specific part of switching to Legacy mode. + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt SetLegacyMode(); + + /** + Called by the LDD to handle the device specific part of switching to GCE mode. + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt SetGceMode(); + + /** + Called by the LDD to handle the device specific part of setting the rotation. + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt SetRotation(TInt aRotation); + + /** + Called by the LDD to handle the device specific part of posting a User Buffer. + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt PostUserBuffer(TBufferNode* aNode); + + /** + Called by the LDD to handle the device specific part of posting a Composition Buffer + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt PostCompositionBuffer(TBufferNode* aNode); + + /** + Called by the LDD to handle the device specific part of posting the Legacy Buffuer + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt PostLegacyBuffer(); + + /** + Called by the LDD to handle device specific cleanup operations when a channel is closed. + + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt CloseMsg(); + + /** + Called by the LDD to handle device specific initialisation tasks when a channel is opened. + + @param aUnit The screen/hardware unit number. + @return KErrNone if successful; or one of the other system wide error codes. + */ + virtual TInt CreateChannelSetup(TInt aUnit); + + /** + Called by the LDD in order to detect whether a post operation is pending. This type of + information is specific to the actual physical device. + + @return ETrue if a Post operation is pending otherwise EFalse. + */ + virtual TBool PostPending(); + + /** + Called by the LDD to retrieve the DFC Queue created in the PDD. + + @param aUnit The screen/hardware unit number. + @return A pointer to the TDfcQue object created in the PDD. + */ + virtual TDfcQue* DfcQ(TInt aUnit); + +public: + static void VSyncDfcFn(TAny* aChannel); + +private: + TDfcQue* iDfcQ; + + //generic display info + TVideoInfoV01 iScreenInfo; + + //Pointer to a buffer in the Pending state + TBufferNode* iPendingBuffer; + + //Pointer to a buffer in the Active state + TBufferNode* iActiveBuffer; + + DChunk * iChunk; + TLcdUserCallBack* iLcdCallback; + + public: + TDfc iVSyncDfc; + }; + + +/** + PDD Factory class + */ + +class DDisplayPddFactory : public DPhysicalDevice + { +public: + DDisplayPddFactory(); + + virtual TInt Install(); + virtual void GetCaps(TDes8& aDes) const; + virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); + virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer); + }; + +#endif diff -r 50cddb1eb3af -r 72a7468afdd4 baseport/syborg/svpframebuffer/svpframebuffer.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/baseport/syborg/svpframebuffer/svpframebuffer.mmp Sat Feb 27 19:18:04 2010 +0000 @@ -0,0 +1,40 @@ +/* +* 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: +* +*/ + +#include +#include "kernel/kern_ext.mmh" + +TARGET VariantTarget(svpframebuffer,dll) +TARGETTYPE kext + +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) +SYSTEMINCLUDE AsspNKernIncludePath +SYSTEMINCLUDE . + +SOURCEPATH . +SOURCE svpframebuffer.cpp + +LIBRARY PlatformLib + +EPOCALLOWDLLDATA + +UID 0x1000008d 0x100039e8 +VENDORID 0x70000001 + +ROMTARGET lcd.dll + +CAPABILITY all diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/devtree.c --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/devtree.c Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/devtree.c Sat Feb 27 19:18:04 2010 +0000 @@ -26,6 +26,7 @@ #include "devtree.h" #include "hw/boards.h" #include "libfdt/libfdt.h" +#include "qemu-char.h" #define BADF(fmt, args...) \ do { fprintf(stderr, "error: " fmt , ##args); exit(1);} while (0) @@ -413,7 +414,15 @@ if (propstr) { i = sscanf(propstr, "serial%d", &n); if (i == 1 && n >= 0 && n < MAX_SERIAL_PORTS) + { + if (!serial_hds[n]) + { + const char* target = fdt_getprop_string(dt, node, "target"); + if (target) + serial_hds[n] = qemu_chr_open(propstr, target); + } d->chardev = serial_hds[n]; + } } } find_properties(d); diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_serial.py --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_serial.py Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_serial.py Sat Feb 27 19:18:04 2010 +0000 @@ -1,4 +1,6 @@ import qemu +import os +import sys class syborg_serial(qemu.devclass): REG_ID = 0 @@ -127,6 +129,57 @@ regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)] irqs = 1 name = "syborg,serial" - properties = {"fifo-size":16, "chardev":None} + properties = {"fifo-size":16, "chardev":None, "target": ""} qemu.register_device(syborg_serial) + +class syborg_modem(syborg_serial): + + def create(self): + syborg_serial.create(self) + + # Find the path of the emulator executable + path = os.path.dirname(sys.executable) + executable = os.getenv("SVP_MODEM_EXECUTABLE") + if None == executable: + executable = self.modem_executable + + executable_name = executable + fq_executable = os.path.join(path, executable_name) + print(fq_executable) + + if not os.path.exists(fq_executable): + executable_name = executable + ".exe" + fq_executable = os.path.join(path, executable_name) + + if not os.path.exists(fq_executable): + sys.exit("Could not locate modem executable '" + executable + "' in '" + path + "'!\n") + + # Attempt to find the correct port from the target spec + target = self.properties["target"] + + if not(target.startswith("tcp:") or target.startswith("udp:")): + sys.exit("Modem device is not accessed via an acceptable socket.") + + target = target[4:] + port_start_idx = target.find(":"); + port_end_idx = target.find(",") + if -1 == port_start_idx: + sys.exit("Could not extract port number from modem target spec!") + + port = "" + if -1 == port_end_idx: + port = target[port_start_idx + 1:] + else: + port = target[port_start_idx + 1:port_end_idx] + + os.spawnl(os.P_NOWAIT, fq_executable, executable_name, "-p", port) + self.chardev.handle_connect() + + # Name property override. + name = "syborg,serial,modem" + + # Default modem executable + modem_executable = "phonesim" + +qemu.register_device(syborg_modem) diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c Sat Feb 27 19:18:04 2010 +0000 @@ -1072,6 +1072,17 @@ return 0; } +static PyObject *qemu_py_chardev_handle_connect(qemu_py_chardev *self, + PyObject *args) +{ + if (!self->chr) + Py_RETURN_NONE; + + qemu_chr_connect(self->chr); + + Py_RETURN_NONE; +} + static PyObject *qemu_py_chardev_set_handlers(qemu_py_chardev *self, PyObject *args, PyObject *kwds) { @@ -1147,6 +1158,9 @@ }; static PyMethodDef qemu_py_chardev_methods[] = { + {"handle_connect", (PyCFunction)qemu_py_chardev_handle_connect, + METH_NOARGS, + "Handle character device connect if required"}, {"set_handlers", (PyCFunction)qemu_py_chardev_set_handlers, METH_VARARGS|METH_KEYWORDS, "Set event handlers"}, diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.c --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.c Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.c Sat Feb 27 19:18:04 2010 +0000 @@ -123,6 +123,12 @@ } } +void qemu_chr_connect(CharDriverState *s) +{ + if (s->chr_connect) + s->chr_connect(s); +} + int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) { return s->chr_write(s, buf, len); @@ -605,6 +611,20 @@ return qemu_chr_open_fd(-1, fd_out); } +static CharDriverState *qemu_chr_open_tempfile_out(const char *temp_file) +{ + CharDriverState *ret = NULL; + const char *temp_format = "/tmp/%s"; + char *fname = qemu_mallocz(sizeof(char) * (strlen(temp_path) + strlen(temp_file))); + if (fname) + { + sprintf(fname, temp_format, temp_file); + ret = qemu_chr_open_file_out(fname); + qemu_free(fname); + } + return ret; +} + static CharDriverState *qemu_chr_open_pipe(const char *filename) { int fd_in, fd_out; @@ -1757,6 +1777,29 @@ return qemu_chr_open_win_file(fd_out); } + +static CharDriverState *qemu_chr_open_win_tempfile_out(const char *temp_file) +{ + CharDriverState *ret = NULL; + char* fname; + const char* temp_format = "%s\\%s"; + const char* temp_path; + + temp_path = getenv("TEMP"); + if (temp_path) + { + fname = qemu_mallocz(sizeof(char) * (strlen(temp_path) + strlen(temp_file) + strlen(temp_format))); + if (fname) + { + sprintf(fname, temp_format, temp_path, temp_file); + ret = qemu_chr_open_win_file_out(fname); + qemu_free(fname); + } + } + + return ret; +} + #endif /* !_WIN32 */ /***********************************************************/ @@ -1886,6 +1929,8 @@ int do_telnetopt; int do_nodelay; int is_unix; + int wait_connect; + int device_handles_connect; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -2063,6 +2108,26 @@ tcp_chr_connect(chr); } +static void tcp_chr_do_connect(CharDriverState* chr) +{ + TCPCharDriver *driver = (TCPCharDriver*)chr->opaque; + if (driver->device_handles_connect) + { + if (-1 != driver->listen_fd) + { + printf("QEMU waiting for connection...\n"); + tcp_chr_accept(chr); + socket_set_nonblock(driver->listen_fd); + } + else + { + driver->connected = 1; + socket_set_nodelay(driver->fd); + tcp_chr_connect(chr); + } + } +} + static void tcp_chr_close(CharDriverState *chr) { TCPCharDriver *s = chr->opaque; @@ -2083,6 +2148,7 @@ int is_listen = 0; int is_waitconnect = 1; int do_nodelay = 0; + int is_device_handles_connect = 0; const char *ptr; ptr = host_str; @@ -2096,6 +2162,8 @@ do_nodelay = 1; } else if (!strncmp(ptr,"to=",3)) { /* nothing, inet_listen() parses this one */; + } else if (!strncmp(ptr, "devicehandlesconnect", 20) && !is_unix) { + is_device_handles_connect = 1; } else { printf("Unknown option: %s\n", ptr); goto fail; @@ -2107,6 +2175,7 @@ chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) goto fail; + s = qemu_mallocz(sizeof(TCPCharDriver)); if (!s) goto fail; @@ -2147,10 +2216,13 @@ s->listen_fd = -1; s->is_unix = is_unix; s->do_nodelay = do_nodelay && !is_unix; + s->wait_connect = is_waitconnect; + s->device_handles_connect = is_device_handles_connect; chr->opaque = s; chr->chr_write = tcp_chr_write; chr->chr_close = tcp_chr_close; + chr->chr_connect = tcp_chr_do_connect; if (is_listen) { s->listen_fd = fd; @@ -2158,13 +2230,17 @@ if (is_telnet) s->do_telnetopt = 1; } else { - s->connected = 1; s->fd = fd; - socket_set_nodelay(fd); - tcp_chr_connect(chr); + + if (!is_device_handles_connect) + { + s->connected = 1; + socket_set_nodelay(fd); + tcp_chr_connect(chr); + } } - if (is_listen && is_waitconnect) { + if (is_listen && is_waitconnect && !is_device_handles_connect) { printf("QEMU waiting for connection on: %s\n", chr->filename ? chr->filename : host_str); tcp_chr_accept(chr); @@ -2220,6 +2296,8 @@ chr = qemu_chr_open_tcp(p, 0, 1); } else if (strstart(filename, "file:", &p)) { chr = qemu_chr_open_file_out(p); + } else if (strstart(filename, "tempfile:", &p)) { + chr = qemu_chr_open_tempfile_out(p); } else if (strstart(filename, "pipe:", &p)) { chr = qemu_chr_open_pipe(p); } else if (!strcmp(filename, "pty")) { @@ -2252,6 +2330,9 @@ if (strstart(filename, "file:", &p)) { chr = qemu_chr_open_win_file_out(p); } else + if (strstart(filename, "tempfile:", &p)) { + chr = qemu_chr_open_win_tempfile_out(p); + } else if (strstart(filename, "stdio", &p)) { return qemu_chr_open_win_stdio(filename); } else diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.h --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.h Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/qemu-char.h Sat Feb 27 19:18:04 2010 +0000 @@ -46,6 +46,7 @@ int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + void (*chr_connect)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -64,6 +65,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename); void qemu_chr_close(CharDriverState *chr); void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); +void qemu_chr_connect(CharDriverState *s); int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); void qemu_chr_send_event(CharDriverState *s, int event); void qemu_chr_add_handlers(CharDriverState *s, diff -r 50cddb1eb3af -r 72a7468afdd4 symbian-qemu-0.9.1-12/qemu-symbian-svp/vl.c --- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/vl.c Fri Jan 08 12:04:26 2010 +0000 +++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/vl.c Sat Feb 27 19:18:04 2010 +0000 @@ -4666,14 +4666,12 @@ cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; monitor_device = "vc"; - - serial_devices[0] = "vc:80Cx24C"; - for(i = 1; i < MAX_SERIAL_PORTS; i++) + + for(i = 0; i < MAX_SERIAL_PORTS; i++) serial_devices[i] = NULL; serial_device_index = 0; - - parallel_devices[0] = "vc:640x480"; - for(i = 1; i < MAX_PARALLEL_PORTS; i++) + + for(i = 0; i < MAX_PARALLEL_PORTS; i++) parallel_devices[i] = NULL; parallel_device_index = 0;