# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1265067550 -7200 # Node ID cec860690d41acd3de631327bc626a78e469a001 Revision: 201005 Kit: 201005 diff -r 000000000000 -r cec860690d41 boardsupport_info/boardsupport_metadata/boardsupport_metadata.mrp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boardsupport_info/boardsupport_metadata/boardsupport_metadata.mrp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,6 @@ +component boardsupport_metadata +source \sf\os\boardsupport\boardsupport_info\boardsupport_metadata +source \sf\os\boardsupport\package_definition.xml +source \sf\os\boardsupport\distribution.policy.s60 +notes_source \component_defs\release.src +ipr T diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/base_wins.history.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/base_wins.history.xml Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,6 @@ + + + + In Kernel Architecture, treated as a hardware target variant, Symbian OS emulation which maps OS services and logical devices to Win32 APIs and local hardware e.g. network devices and comms ports on the Windows host machine. Single process implementation using Windows threads to emulate Symbian OS processes, valuable high level programming platform which creates infidelities for low level and device dependent programming compared to hardware targets. + + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/base_wins.mrp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/base_wins.mrp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,38 @@ +# +# 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 "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: +# +# component name "Emulator" + +component base_wins + +source \sf\os\boardsupport\emulator\emulatorbsp +binary \sf\os\boardsupport\emulator\emulatorbsp all +exports \sf\os\boardsupport\emulator\emulatorbsp + +-export_file \sf\os\boardsupport\emulator\emulatorbsp\documentation\wins_ether_drv_howto.txt \epoc32\engdoc\ethernet\wins_ether_drv_howto.txt + +notes_source \component_defs\release.src + + +# == comments appear after the line they describe == +ipr E +ipr B \sf\os\boardsupport\emulator\emulatorbsp\specific\sdcard +# Must only be distributed to parties who have signed an agreement with the SD-3C LLC +ipr B \sf\os\boardsupport\emulator\emulatorbsp\specific\sdcard\sdcard4c +# Must only be distributed to parties who have signed an agreement with the 4C LLC +ipr T \sf\os\boardsupport\emulator\emulatorbsp\test +ipr T \sf\os\boardsupport\emulator\emulatorbsp\win_drive +ipr F \sf\os\boardsupport\emulator\emulatorbsp\wpdpack + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/bld.inf Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,88 @@ +// 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 "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: +// wins/bld.inf +// +// + +PRJ_PLATFORMS +WINS WINSCW + +PRJ_EXPORTS + +documentation/wins_ether_drv_howto.txt /epoc32/engdoc/ethernet/ // + + +inc/variantmediadef.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/variantmediadef.h) +variant.mmh SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/variant.mmh) +specific/winscomm.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/winscomm.h) +specific/winscomm.inl SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/winscomm.inl) +inc/nand_fbr_offset.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/nand/nand_fbr_offset.h) +inc/winsgui.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(wins/winsgui.h) +:zip emuldrives.zip +wpdpack/drivers/winpcap.exe /epoc32/tools/winpcap.exe // +wpdpack/lib/packet.lib /epoc32/release/tools/udeb/packet.lib // +wpdpack/lib/wpcap.lib /epoc32/release/tools/udeb/wpcap.lib // + +PRJ_MMPFILES +../../../kernelhwsrv/kernel/eka/kernel/ekern +../../../kernelhwsrv/kernel/eka/kernel/kc_exe +vwins +winsgui +displayldd +cakdwins +// SYM_BRANCH : Delete old sound driver +//dasnwins +../../../kernelhwsrv/kernel/eka/drivers/medint/medint +medlfs +serialldd +serialpdd +epbusv +enet +soundsc +estart +econsnogui +../../../kernelhwsrv/kernel/eka/drivers/trace/btracex + +win_drive + +hcr/hcr + +PRJ_EXTENSIONS +start extension base/config + +option PREFIX +option SOURCE $(EXTENSION_ROOT)/hal +option HALPATH $(EXTENSION_ROOT)/../../../kernelhwsrv/halservices/hal/../. + +end + +PRJ_MMPFILES +hal/hal + +// NAND selectable page offset for FBR + +PRJ_EXTENSIONS +start extension base/nand_fbr_offset + +#ifdef SYMBIAN_OLD_EXPORT_LOCATION +option INC_PATH /epoc32/include +#else +option INC_PATH /epoc32/include/platform +#endif + +option SRCDIR $(EXTENSION_ROOT)/inc +option TARGETDIR $(INC_PATH)/wins/nand + +end + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/bwins/econsnoguiU.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/bwins/econsnoguiU.def Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,3 @@ +EXPORTS + NewConsole @ 1 NONAME + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/bwins/vwinsu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/bwins/vwinsu.def Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,10 @@ +EXPORTS + ?VariantInitialise@@YAPAVAsic@@H@Z @ 1 NONAME ; class Asic * __cdecl VariantInitialise(int) + ??0DWinsUiBase@@IAE@XZ @ 2 NONAME ; protected: __thiscall DWinsUiBase::DWinsUiBase(void) + ?AssertWakeupSignal@Wins@@QAEXXZ @ 3 NONAME ; public: void __thiscall Wins::AssertWakeupSignal(void) + ?WakeupEvent@Wins@@QAEXXZ @ 4 NONAME ; public: void __thiscall Wins::WakeupEvent(void) + ?CurrentPBusDevicePtr@Wins@@SAPAHXZ @ 5 NONAME ; public: static int * __cdecl Wins::CurrentPBusDevicePtr(void) + ?MediaChangeCallBack@Wins@@SAXXZ @ 6 NONAME ; public: static void __cdecl Wins::MediaChangeCallBack(void) + ?MediaDoorOpenPtr@Wins@@SAPAHXZ @ 7 NONAME ; public: static int * __cdecl Wins::MediaDoorOpenPtr(void) + ?SetMediaChangeCallBackPtr@Wins@@SAXP6AXPAX@Z0@Z @ 8 NONAME ; public: static void __cdecl Wins::SetMediaChangeCallBackPtr(void (__cdecl*)(void *),void *) + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/bwins/winsguiu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/bwins/winsguiu.def Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,3 @@ +EXPORTS + ?CurrentConfiguration@WinsGui@@SAHXZ @ 1 NONAME ; public: static int __cdecl WinsGui::CurrentConfiguration(void) + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/cakdwins.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/cakdwins.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,35 @@ +// 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 "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: +// wins/cakdwins.mmp +// +// + +target ekdata.dll +targettype dll + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +sourcepath specific +source keymap.cpp + +library euser.lib + +linkas ekdata.dll +deffile ../../../kernelhwsrv/kernel/eka/bwins/ekdata.def +nostrictdef + +uid 0x1000008d 0x100039e0 +VENDORID 0x70000001 + +capability all diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/displayldd.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/displayldd.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/displayldd.mmp +// +// + +#include + +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) +USERINCLUDE inc +userinclude inc + +target display0.ldd +targettype ldd + +sourcepath specific +source display_dev.cpp +source display_chan.cpp + +start wins +win32_headers +win32_library kernel32.lib user32.lib gdi32.lib +#if defined(VC32) +win32_library msvcrt.lib +#endif + +end + +uid 0x100000af + +capability all + +VENDORID 0x70000001 + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/documentation/wins_ether_drv_howto.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/documentation/wins_ether_drv_howto.txt Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,193 @@ +/* +* 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 "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: +* +*/ +HOWTO for Wins Ethernet Driver + +0. Pre-requisities +The implementation of Wins Ethernet driver makes use of packet capturing library: +WinPcap, Release 2.2. This software sets the network card of the PC, on which Epoc +Emulator is working, into so called promiscuous mode. The user must be confident that +the environment she/he works in doesn’t forbid such settings. The quickest way +to ensure about it is to contact network administrator. + + +1. Trouble Shooting +The following problems may occur when attempting to use WINS version of Ethernet driver: +* Network application doesn’t send nor receive any packets: two potential reasons: + - bad settings in CommDB - refer to point 4 + - Wpcap not installed - refer to point 2 + +* A panic is raised of category: 'D32ETHER' with one of the following reasons: + 1 meaning: bad MAC address in ini file or entry for it missing or ini file missing + 2 meaning: entry for network interface name missing in ini file or ini file missing + 3 meaning: Wpcap couldn't be initialised - potentially not installed or name + of network interface in .ini file wrong +Panics occur if system is not configured properly, remedy can be found in notes below. + +* Wpcap error may occur - refer to http://winpcap.polito.it/misc/changelog.htm + for advice how to fix the problem (this will require usually upgrading WinPcap + package on user'’ machine). + + +2. Wpcap +Wpcap must be installed on a machine that wishes to use driver. Installation is simple: +WinPcap.exe (located in: \epoc32\tools) +should be run and then instructions should be followed. +If user has already Wpcap installed on his workstation then should try to use +Ethernet driver with this version. In case when it fails he must uninstall existing +Wpcap and install the one from Epoc directory mentioned above. + + +3. Netcards +When Wpcap is already installed, a program called Netcards.exe should be run. +It can be found in \epoc32\tools. +(Note: Netcards uses Wpcap so the latter must be installed first). +It will request user to select network card. Netcards writes a few entries +into \epoc32\data\ethernet.ini file which are read by Epoc Emulator at startup +(ensure that \epoc32\data directory exists). In particular MAC address value for use +by Emulator is determined by the entry named 'ETHER_MAC' (it is recommended that +network administrator was aware of the value of MAC address written there and authorise +it if necessary; according to local conditions any other value preferred +by administrator can be written manually instead of the value written by Netcards). +Ethernet driver for WINS was originally +designed for use in Techview environment which uses ethernet.ini file. Other environments +(like Quartz) may use different .ini file (e.g. \epoc32\data\quartz.ini). A user can +still run Ethernet module in these environments provided that .ini files appropriate +for these environments contain entries written by netcards.exe to ethernet.ini - user can +simply copy them - they are easy to recognise as they begin with ‘ETHER_‘ prefix . + + +4. CommDB +CommDB settings should indicate use of the NIF: ethint.nif and the agent: nullagt.agt. +In current release of Epoc Networking software, data in the database are written by program +called ced.exe, which takes wanted settings from text file: ced.cfg. +Example settings to be put in this file are shown below. In the example it is assumed +that IP address and network mask will be acquired by DHCP protocol: + +############################################################ +## LANBearer +## +[LANBearer] +ADD_SECTION +# COMMDB_ID = 1 + Name=Wins Ethernet + Agent=nullagt.agt + IfName=ethint + LDDFilename=enet + LDDName=Ethernet + PDDFilename=ethernet + PDDName=Ethernet.Wins + PacketDriverName=EtherPkt.drv + LastSocketActivityTimeout=-1 + LastSessionClosedTimeout=-1 + LastSocketClosedTimeout=-1 + FIELD_COUNT=8 +END_ADD + +ADD_SECTION +# COMMDB_ID = 2 + Name=Assabet on-board Ethernet + Agent=nullagt.agt + IfName=ethint + LDDFilename=enet + LDDName=Ethernet + PDDFilename=ethernet + PDDName=Ethernet.Assabet + PacketDriverName=EtherPkt.drv + LastSocketActivityTimeout=-1 + LastSessionClosedTimeout=-1 + LastSocketClosedTimeout=-1 + FIELD_COUNT=8 +END_ADD + +############################################################ +## LANService +## +[LANService] + +ADD_SECTION +# COMMDB_ID = 1 + Name=Ethernet + #IfNetworks=ip,ip6 + IfNetworks=ip + IpNetMask=0.0.0.0 + IpGateway=0.0.0.0 + IpAddrFromServer=TRUE + IpAddr=0.0.0.0 + IpDNSAddrFromServer=TRUE + IpNameServer1=0.0.0.0 + IpNameServer2=0.0.0.0 + FIELD_COUNT=9 +END_ADD + + +############################################################ +## IAP +## +[IAP] +ADD_SECTION +# COMMDB_ID = 1 + Name=Ethernet IAP + IAPService=1 + IAPServiceType=LANService + IAPBearer=1 + IAPBearerType=LANBearer + IAPNetwork=1 + IAPNetworkWeighting=0 + Location=2 + FIELD_COUNT=8 +END_ADD + +ADD_SECTION +# COMMDB_ID = 2 + Name=NT RAS with Null Modem + IAPService=2 + IAPServiceType=DialOutISP + IAPBearer=2 + IAPBearerType=ModemBearer + IAPNetwork=1 + IAPNetworkWeighting=0 + Location=2 + FIELD_COUNT=8 +END_ADD + +############################################################ +## ConnectionPreferences +## +[ConnectionPreferences] + + +ADD_SECTION + Ranking=0 + Direction=OUTGOING + DialogPref=PROMPT + BearerSet=LAN + #IAP=Ethernet IAP + IAP=1 + FIELD_COUNT=5 +END_ADD + +ADD_SECTION + Ranking=1 + Direction=OUTGOING + DialogPref=DONOTPROMPT + BearerSet=LAN +#IAP=Ethernet IAP + IAP=1 + FIELD_COUNT=5 +END_ADD + + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/econsnogui.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/econsnogui.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,37 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/econsnogui.mmp +// econsnogui.dll Implementation of console used when running without a GUI +// +// + +/** + @file +*/ + +TARGET econsnogui.dll +TARGETTYPE dll +UID 0x1000008d 0x100039e7 +DEFFILE bwins/econsnogui.def + +CAPABILITY All + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +SOURCEPATH specific +SOURCE econsnogui.cpp + +LIBRARY euser.lib + +VENDORID 0x70000001 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/emuldrives.zip Binary file emulator/emulatorbsp/emuldrives.zip has changed diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/enet.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/enet.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,43 @@ +// 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 "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: +// wins/enet.mmp +// +// + +#include "kernel/kern_ext.mmh" + +USERINCLUDE inc +USERINCLUDE wpdpack/include +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + +target ethernet.pdd +targettype pdd + +sourcepath specific +source ethernet.cpp + +start wins + +#ifdef WINSCW +win32_library kernel32.lib wpdpack/lib/wpcap.lib +#else +win32_library kernel32.lib wpdpack/lib/wpcap.lib msvcrt.lib +#endif + +end + +capability all + + +VENDORID 0x70000001 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/epbusv.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/epbusv.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,71 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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 "kernel/kern_ext.mmh" + +//#define MMC_SD // Include for MMC+SD build +//#define MMC_SD_CPRM // Include for MMC+SD+CPRM build +//#define MMC_SD_SDIO // Include for MMC+SDIO build + +USERINCLUDE inc +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + +target epbusv.dll +targettype kext + +#if defined(MMC_SD) +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c +sourcepath specific/sdcard/sdcard3c +source pp_sdc.cpp +source pp_sdcv.cpp +library epbussd.lib +#elif defined(MMC_SD_CPRM) +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard4c +sourcepath specific/sdcard/sdcard4c +source pp_cprm.cpp +source pp_cprmv.cpp +library epbussdp.lib +#elif defined(MMC_SD_SDIO) +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard4c +USERINCLUDE ../../../kernelhwsrv/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdio +sourcepath specific/sdcard/sdcard3c/sdio +source pp_sdio.cpp +source pp_sdiov.cpp +library epbussdio.lib +#else +sourcepath specific +source mmc.cpp +source mmcv.cpp +library epbusmmc.lib +#endif + +library ecust.lib +library emulator.lib + +epocallowdlldata + +start wins +win32_library kernel32.lib +#if defined(VC32) +win32_library msvcrt.lib +#endif +end + +uid 0x1000008d 0x10004187 +VENDORID 0x70000001 + +capability all diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/estart.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/estart.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,53 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/estart.mmp +// estart.exe Base Symbian OS startup process +// +// + +/** + @file +*/ + + +TARGET e32strt.exe +CAPABILITY TCB WriteDeviceData DiskAdmin ProtServ AllFiles PowerMgmt + +TARGETTYPE exe + + +SOURCEPATH ../../../kernelhwsrv/userlibandfileserver/fileserver/estart +SOURCE estart.cpp +SOURCEPATH estart +SOURCE estartmain.cpp + +STRICTDEPEND + +USERINCLUDE ../../../kernelhwsrv/userlibandfileserver/fileserver/estart +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +LIBRARY efsrv.lib euser.lib hal.lib +LIBRARY domaincli.lib + +#ifdef WINS +LIBRARY emulator.lib +#endif + +START WINS +BASEADDRESS 0x62000000 +win32_library kernel32.lib +END + +UID 0 0x10272C04 +VENDORID 0x70000001 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/estart/estart.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/estart/estart.txt Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,67 @@ +# Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "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: +# + +#R: 2 EFAT32 FAT 0 FS_FORMAT_CORRUPT # MMC - Slot 0, partition 1 +#S: 4 EFAT32 FAT 0 FS_FORMAT_CORRUPT # MMC - Slot 1, partition 1 +T: 3 EFAT32 FAT 0 FS_FORMAT_CORRUPT # MMC - Slot 1, partition 0 +U: 5 EFAT32 FAT 0 FS_FORMAT_CORRUPT # NAND - USER DATA +V: 6 EROFS ROFS 0 FS_DISMNT_CORRUPT # NAND - CODE +W: 8 ELFFS LFFS 0 FS_FORMAT_CORRUPT # LFFS +X: 1 EFAT32 FAT 0 FS_FORMAT_CORRUPT # MMC - Slot 0, partition 0 +Y: 0 EFAT32 FAT 0 FS_FORMAT_COLD,FS_SYNC_DRIVE # IRAM + + +[DriveT] +FAT_LeafDirCacheSize 32 +FAT_DirCacheSizeMin 128 +FAT_DirCacheSizeMax 256 + +FileCacheSize 16 +FileCacheRead ON + +[DriveU] +FAT_LeafDirCacheSize 32 +FAT_DirCacheSizeMin 128 +FAT_DirCacheSizeMax 256 + +[DriveX] +FAT_LeafDirCacheSize 32 +FAT_DirCacheSizeMin 128 +FAT_DirCacheSizeMax 256 + +FileCacheSize 256 +FairSchedulingLen 64 + +FileCacheRead ON +FileCacheReadAhead ON +FileCacheWrite ON + +ClosedFileKeepAliveTime 3000 +DirtyDataFlushTime 3000 + +[DriveW] +FileCacheRead ON +FileCacheWrite ENABLED +FairSchedulingLen 64 + +[FileCache] +GlobalCacheEnabled ON +GlobalCacheSize 32768 +GlobalCacheMaxLockedSize 768 +LowMemoryThreshold 10 + +[CacheMemory] +GlobalCacheMemorySize 32768 +LowMemoryThreshold 10 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/estart/estartmain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/estart/estartmain.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,331 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\estart\estartmain.cpp +// +// + +#include +#include +#include +#include "estart.h" + +#include +#include +#define WIN32_LEAN_AND_MEAN +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union +#include +#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union + + + +_LIT(KLitAddFsFail,"Add fs fail"); +_LIT(KLitConnectFsFail2,"Connect fs 2 fail"); +_LIT(KLitNoWS,"No WSERV"); +_LIT(KStartupModeFail,"Get startup mode failed"); +_LIT(KLocalFsName,"elocal"); + +class TWinsFSStartup : public TFSStartup + { +public: + virtual TInt StartSystem(); + virtual TInt DefaultLocalDrive(TInt aLocalDrive); + virtual TPtrC LocalDriveMappingFileName(); +#if !defined(AUTODETECT_DISABLE) + virtual TInt GetNextStandardFSInfoEntry(const SFileSystemInfo** anEntry,TInt aPos); +#endif +public: + void LocalFSInitialisation(); +protected: + TInt GetStartupMode(); + }; + +#if !defined(AUTODETECT_DISABLE) +TInt DetectEmulRAM(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType==EMediaRam) + return KErrNone; + return KErrGeneral; + } + +TInt DetectEmul_CF_FAT(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType!=EMediaHardDisk || !(caps.iDriveAtt & KDriveAttRemovable)) + return KErrGeneral; + if (cr==KErrNotReady) + return KErrNone; // removable and not ready - assume fat + if (cr==KErrNone && PartitionIsFAT(caps.iPartitionType)) + return KErrNone; + return KErrGeneral; + } + +TInt DetectEmul_CF_FAT32(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType!=EMediaHardDisk || !(caps.iDriveAtt & KDriveAttRemovable)) + return KErrGeneral; + if (cr==KErrNotReady) + return KErrNone; // removable and not ready - assume fat + if (cr==KErrNone && (PartitionIsFAT32(caps.iPartitionType) || PartitionIsFAT(caps.iPartitionType)) ) + return KErrNone; + return KErrGeneral; + } +#endif + + +_LIT(KLocalDriveMappingFileSysBin,"Z:\\SYS\\DATA\\ESTART.TXT"); +TPtrC TWinsFSStartup::LocalDriveMappingFileName() + { + __ASSERT_ALWAYS(InitCompositeFileSystem()==KErrNone,User::Panic(_L("InitCompositeFileSystem failed."),0)); + return(KLocalDriveMappingFileSysBin()); + } + +LOCAL_C void AutoRun() + { + // Ensure that any background initialisation completes before auto-running + RProcess me; + me.SetPriority(EPriorityLow); + const char* autorun = EmulatorAutoRun(); + if (autorun) + { + TInt r = KErrNone; + const char* cmdline = EmulatorCommandLine(); + TFileName exe; + exe.Copy(TPtrC8((const TText8*)autorun)); + TPtrC8 c((const TText8*)cmdline); + HBufC* command = HBufC::New(c.Length()); + if (!command) + r = KErrNoMemory; + else + { + TPtr ptr(command->Des()); + ptr.Copy(c); + RProcess p; + r = p.Create(exe, *command); + if (r == KErrNone) + { + TRequestStatus s; + p.Logon(s); + me.SetPriority(EPriorityHigh); // ensure we detect termination early + p.Resume(); + p.Close(); + User::WaitForRequest(s); + r = s.Int(); + } + } + Emulator::Escape(); // make sure we don't get suspended while exiting + ExitProcess(r); + } + } + +const TInt WinsDefaultLocalDrives[KMaxLocalDrives]= + { + EDriveY, //0 + EDriveX, //1 MMC - Slot 0, partition 0 + KDriveInvalid, //2 MMC - Slot 0, partition 1 + EDriveT, //3 MMC - Slot 1, partition 0 + KDriveInvalid, //4 MMC - Slot 1, partition 1 + EDriveU, //5 NAND - USER DATA + EDriveV, //6 NAND - CODE + KDriveInvalid, //7 + EDriveW, //8 + KDriveInvalid, //9 + KDriveInvalid, //10 + KDriveInvalid, //11 + KDriveInvalid, //12 + KDriveInvalid, //13 + KDriveInvalid, //14 + KDriveInvalid //15 + }; + +TInt TWinsFSStartup::DefaultLocalDrive(TInt aLocalDrive) + { + + return(WinsDefaultLocalDrives[aLocalDrive]); + } + +#if !defined(AUTODETECT_DISABLE) +const TInt KMaxWinsFSInfoTableEntries=7; +LOCAL_D const SFileSystemInfo FileSystems[KMaxWinsFSInfoTableEntries] = + { + {DetectEmulRAM, _S("efat32"), _S("fat"), 0, FS_FORMAT_CORRUPT}, + {DetectEmul_CF_FAT32,_S("efat32"), _S("fat"), 0, FS_FORMAT_CORRUPT}, + {DetectFtl, _S("efat32"), _S("fat"), 0, FS_FORMAT_CORRUPT}, + {DetectRofs, _S("erofs"), _S("rofs"), 0, FS_DISMNT_CORRUPT}, + {DetectEneaLFFS, _S("elffs"), _S("lffs"), 0, FS_FORMAT_CORRUPT}, + {DetectIso9660, _S("iso9660"), 0, 0, 0}, + {DetectNtfs, _S("ntfs"), 0, 0, 0}, + }; + +// additional structure for DetectFtl entry with extension set to "0" +LOCAL_D const SFileSystemInfo FileSystemForDetectFtl = + {DetectFtl, _S("efat32"), _S("fat"), 0, FS_FORMAT_CORRUPT}; + + +TInt TWinsFSStartup::GetNextStandardFSInfoEntry(const SFileSystemInfo** anEntry,TInt aPos) + { + if (aPos root=_L("?:\\"); + for(i=0;i +#include + +// ECPUSpeed +TInt ProcessCPUSpeed(TInt /*aDeviceNumber*/, TInt /*aAttrib*/, TBool aSet, TAny* aInOut) + { + return UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalCPUSpeed, (TAny*)aSet, aInOut); + } + +// +TInt GetDisplayNumberOfScreens(TInt /*aDeviceNumber*/, TInt /*aAttrib*/, TBool /*aSet*/, TAny* aInOut) + { + return UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalNumberOfScreens, NULL, aInOut); + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hal/hal.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hal/hal.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,53 @@ +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/hal/hal.mmp +// hal.dll Dummy HAL library +// +// + +/** + @file +*/ + +#include + +TARGET hal.dll +TARGETTYPE dll +linkas hal.dll +noexportlibrary + +SOURCEPATH ../../../../kernelhwsrv/halservices/hal/src +SOURCE hal_main.cpp userhal.cpp + +SOURCEPATH . +SOURCE hal.cpp + +SOURCEPATH /epoc32/build/generatedcpp/hal +SOURCE VariantTarget(values,cpp) VariantTarget(config,cpp) + + +SYMBIAN_BASE_SYSTEMINCLUDE(kernel) +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +LIBRARY euser.lib +DEFFILE ../../../../kernelhwsrv/halservices/hal/bwins/hal.def + +UID 0x1000008d 0x100039e8 +VENDORID 0x70000001 + +START WINS +BASEADDRESS 0x6b000000 +END + +capability all diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hal/values.hda --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hal/values.hda Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,68 @@ +EManufacturer=psion +EManufacturerHardwareRev=0x1 +EManufacturerSoftwareRev=0x100 +EManufacturerSoftwareBuild=0x250 +EModel=0x4d24 +EMachineUid=Win32Emulator +EDeviceFamily=crystal +EDeviceFamilyRev=0x001 +ECPU=x86 +ECPUArch=0x700 +ECPUABI=msvc +// ESystemStartupReason=cold +// ESystemException=0 +ESystemTickPeriod=15625 +EMemoryRAM=128 +EMemoryRAMFree=128 +EMemoryROM=16 +EMemoryPageSize=0x1000 +EPowerGood=1 +EPowerBackup=0 +EPowerExternal=1 +EKeyboard=full +EKeyboardDeviceKeys=3 +EKeyboardAppKeys=9 +EKeyboardClick=1 +EKeyboardClickState=1 +EKeyboardClickVolume=0 +EKeyboardClickVolumeMax=1 +EDisplayState=1 +EBacklight=0 +EPen=0 +EPenDisplayOn=1 +EMouse=1 +EMouseState=1 +EMouseSpeed=1 +EMouseAcceleration=1 +EMouseButtons=2 +EMouseButtonState=0 +ECaseSwitch=0 +ECaseSwitchDisplayOn=1 +ECaseSwitchDisplayOff=1 +ELEDs=2 +ELEDmask=0 +EIntegratedPhone=0 +ELanguageIndex=0 +EMaxRAMDriveSize=4194304 +EClipboardDrive=2 +ESystemDrive=0xffffffff +EDisplayNumberOfScreens=1 +EFastCounterCountsUp=1 +ECustomResourceDrive=0xffff +ETimeNonSecureOffset=0 +EPointer3D=1 +EPointer3DMaxProximity=-100 +EPointer3DThetaSupported=1 +EPointer3DPhiSupported=1 +EPointer3DRotationSupported=1 +EPointer3DPressureSupported=1 +EPointer3DProximityStep=5 +EPointerMaxPointers=8 +EPointerNumberOfPointers=6 +EPointer3DMaxPressure=5000 +EPointer3DPressureStep=500 +EPointer3DEnterHighPressureThreshold=0x7fffffff +EPointer3DExitHighPressureThreshold=-0x7fffffff +EPointer3DEnterCloseProximityThreshold=0x7fffffff +EPointer3DExitCloseProximityThreshold=-0x7fffffff +ENumCpus=1 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hcr/hcr.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hcr/hcr.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,52 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// This file is part of the EPOC Emulator Variant Base Port +// Hardware Configuration Respoitory Platform Specific Layer (PSL) +// + + +// Uncomment and rebuild if you require trace messages from the HCR extension +// macro HCR_TRACE + +// Uncomment if you want HCR PIL to load 'z:\sys\data\hcr.dat' as the Core +// Image file repository because rombuild tool not yet updating ROM header. +// Must always be defined on Emulator based HCR projects. +macro HCRTEST_COREIMG_DONTUSE_ROMHDR + + +// -- PIL Statements ---------------------------------------------------------- +// + + +#include "../../../../kernelhwsrv/kernel/eka/drivers/hcr/hcr.mmh" + +deffile ../../../../kernelhwsrv/kernel/eka/~/hcr.def + +userinclude ../../../../kernelhwsrv/kernel/eka/drivers/hcr + +sourcepath ../../../../kernelhwsrv/kernel/eka/drivers/hcr +source HCR_PIL_SOURCE + + +// -- PSL Statements ---------------------------------------------------------- +// + +sourcepath . +source hcr_psl.cpp +source hcr_psl_config.cpp + +start wins +win32_headers +end + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hcr/hcr_psl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hcr/hcr_psl.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,114 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// This file is part of the EPOC Emulator Variant Base Port +// Hardware Configuration Repository Platform Specific Layer (PSL) +// + + +// -- INCLUDES ---------------------------------------------------------------- + + +#include "hcr_debug.h" + +#include "hcr_hai.h" + + + +// -- GLOBALS ----------------------------------------------------------------- + + +GLREF_C HCR::SRepositoryCompiled gRepository; + + +// -- CLASSES- ---------------------------------------------------------------- + + +class HCRVariant : public HCR::MVariant + { + +public: + + HCRVariant(); + virtual ~HCRVariant(); + +public: + + TInt Initialise(); + + TBool IgnoreCoreImgRepository(); + TInt GetCompiledRepositoryAddress( TAny* & aAddr); + TInt GetOverrideRepositoryAddress( TAny* & aAddr); + + }; + + + + +// -- METHODS ----------------------------------------------------------------- + + +HCRVariant::HCRVariant() + { + HCR_FUNC("HCRVariant"); + } + + +HCRVariant::~HCRVariant() + { + HCR_FUNC("~HCRVariant"); + } + + +TInt HCRVariant::Initialise() + { + HCR_FUNC("HCRVariant::Initialise"); + + HCR_TRACE_RETURN(KErrNone); + } + + +TInt HCRVariant::GetCompiledRepositoryAddress( TAny* & aAddr) + { + HCR_FUNC("HCRVariant::GetCompiledRepositoryAddress"); + + aAddr = static_cast(&gRepository); + HCR_TRACE_RETURN(KErrNone); + } + +TBool HCRVariant::IgnoreCoreImgRepository() + { + HCR_FUNC("HCRVariant::IgnoreCoreImgRepository"); + + HCR_TRACE_RETURN(EFalse); + } + +TInt HCRVariant::GetOverrideRepositoryAddress( TAny* &) + { + HCR_FUNC("HCRVariant::GetRAMRepositoryAddress"); + + // OverrideRepository not supported in EPOC Emulator version + + HCR_TRACE_RETURN(KErrNotSupported); + } + + +// -- ENTRY POINTS ------------------------------------------------------------ + + +GLDEF_C HCR::MVariant* CreateHCRVariant() + { + HCR_FUNC("CreateHCRVariant"); + + return new HCRVariant; + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hcr/hcr_psl_config.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hcr/hcr_psl_config.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,80 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// This file is part of the EPOC Emulator Variant Base Port +// Hardware Configuration Respoitory Platform Specific Layer (PSL) +// + + +/** +@file hcr_psl_config.cpp +File provides the compiled repository (currently empty) EPOC Emulator platform. + +@internalTechnology +*/ + +// -- HCR INCLUDES ------------------------------------------------------------ + +#include "hcrconfig.h" + +#include "hcr_hai.h" +#include "hcr_uids.h" + + +using namespace HCR; + + + +// -- HCR BSP SETTING INCLUDES ------------------------------------------------ + +// Includes for setting published by base port ASSP/SOC interconnections +// e.g. #include "hcr_psl_config_mha_inc.inl" + + + + +// -- HCR BSP LARGE SETTING DATA (LSD) VALUES --------------------------------- + +// Includes for setting published by base port ASSP/SOC interconnections +// e.g. #include "hcr_psl_config_mha_lsd.inl" + + + + +// -- HCR BSP SETTINGS LIST --------------------------------------------------- + +SSettingC gSettingsList[] = + { + +// Includes for setting published by base port ASSP/SOC interconnections +// e.g. #include "hcr_psl_config_mha.inl" + + HCR_LAST_SETTING + }; + + +SRepositoryBase gHeader = + { + HCR_FINGER_PRINT, + EReposCompiled, + KRepositoryFirstVersion, + EReposReadOnly, + HCR_SETTING_COUNT(gSettingsList) + }; + + +GLDEF_C SRepositoryCompiled gRepository = + { + &gHeader, + gSettingsList + }; diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/hcr/hcrconfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/hcr/hcrconfig.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,46 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// This file is part of the EPOC Emulator Variant Base Port +// Hardware Configuration Repository Published Setting IDs header. +// + +/** +@file hcrconfig.h +File provides const uint definitions for the published set of HCR settings +identifiers applicable to the EPOC Emulator base port. +The settings defined in the HCR are examples for "device configuration" for +the platform and not an exhustive list. The HCR is not intended to hold +"feature configuration" which if varied would required significant code +changes in the hardware consumer component. + +@publishedPartner +@prototype +*/ + +#ifndef HCR_CONFIG_H +#define HCR_CONFIG_H + + + +// -- INCLUDES ---------------------------------------------------------------- + +#include + + +// -- CATEGORY UIDs ----------------------------------------------------------- + +// No category UIDs defined yet + + +#endif // HCR_CONFIG_H diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/display_chan.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/display_chan.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,242 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// + +/** + @file + @publishedPartner + @prototype +*/ + +#ifndef __DISPLAY_CHAN_H__ +#define __DISPLAY_CHAN_H__ + +#include "nk_priv.h" +#include +#include +#include "displayhandler.h" + +struct TBufferAddressA; +class TScreenBuffer; +/** +Logical Channel kernel side class for Display +*/ + + +class DDisplayChannel : public DLogicalChannel + { +public: + // constants + enum { KDisplayChMajorVersionNumber = 1 }; + enum { KDisplayChMinorVersionNumber = 2 }; + enum { KDisplayChBuildVersionNumber = 1 }; +public: + // Duplicate of RDisplayChannel structure, as the header file cannot be used. + class TCaps + { + public: + TVersion iVersion; + }; + + class TRequest + { + public: + inline TRequest(void) : iThread(0), iStatus(0) {} + TBool SetStatus(TThreadMessage& aMsg); + void Complete(TInt aResult); + public: + DThread* iThread; + TRequestStatus* iStatus; + }; + + class TBufferInfo + { + public: + TAny* iAddress; + DChunk* iChunk; + TRequest iRequest; + }; + + enum TDisplayPanic + { + EDisplayPanicNullThreadOnSet = 1, + EDisplayPanicInUse = 2, + EDisplayPanicThreadAlreadySet = 3, + EDisplayPanicNullThreadOnComplete = 4, + EDisplayPanicThreadOpenFailed = 5, + EDisplayPanicWaitForPostMissed = 6, + EDisplayPanicNullArgument = 7, + EDisplayPanicNotYetImplemented = 8, + EDisplayPanicInvalidDimensions = 9, + EDisplayPanicInvalidRotation = 10, + EDisplayPanicInvalidBitDepth = 11, + EDisplayPanicInvalidStride = 12, + EDisplayPanicInvalidWindowHandle = 13, + EDisplayPanicInvalidFrameBuffers = 14, + EDisplayPanicInvalidRefreshRate = 15, + EDisplayPanicInvalidOffset = 16, + EDisplayPanicNoLegacyBuffer = 17 + }; + +public: + DDisplayChannel(void); + ~DDisplayChannel(void); + + // DLogicalChannel implementation + virtual TInt DoCreate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer); + virtual void HandleMsg(TMessageBase* aMsg); + + // Function used by the UI code to set up the buffers. + virtual TInt Initialize(RDisplayChannel::TDisplayInfo& aInfo, + RDisplayChannel::TDisplayRotation aRotation, + HWND aHwnd, RPointerArray& aFrameBuffers, + RPointerArray& aChunks, + TScreenBuffer& aDsaBuffer, + TSize aResolution, + TSize aTwips, + const RDisplayChannel::TPixelFormat aPixelFormatArray[], + const TInt aPixelFormatArraySize, + const RDisplayChannel::TBufferFormat& aBufferFormat); + virtual void SetLegacyBuffer(void *aAddress); + +private: + DDisplayChannel(const DDisplayChannel&); + + // Handlers for the three classes of channel message sent + TInt DoControl(TInt aFunction); + void DoRequest(TInt aFunction); + TInt DoCancel(TInt aRequestMask); + TInt NumberOfResolutions(); + TInt SafePut(TAny* aDst, TAny* aSrc, TInt aBytes); + + void ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo); + static void Panic(TDisplayPanic aPanic); + void ClientPanic(RDisplayChannel::TPanic aPanic); + + inline TBool IsCompositionBuffer(RDisplayChannel::TBufferId aId); + static inline TBool IsLegacyBuffer(RDisplayChannel::TBufferId aId); + static inline TBool IsUserBuffer(RDisplayChannel::TBufferId aId); + inline TBool IsValidBuffer(RDisplayChannel::TBufferId aId); + inline RDisplayChannel::TBufferId NextCompositionBuffer(RDisplayChannel::TBufferId aId); + + static inline TBool IsFlipped(RDisplayChannel::TDisplayRotation aRotation); + + static void VSyncTimerFn(TAny* aDisplayChannel); + void DoVSyncTimer(void); + static void VSyncDfcFn(TAny* aDisplayChannel); + void DoVSync(void); + + TInt PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount); + TInt PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount); + TInt GetCompositionBuffer(TAny** aAddress); + TInt PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount); + TInt WaitForPost(RDisplayChannel::TPostCount* aPostCount); + TInt WaitForDisplayConnect(); + TInt SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation, TBool* aIsBufferPreserved); + TInt RegisterUserBuffer(TInt aChunkHandle, TInt aOffset, RDisplayChannel::TBufferId* aBufferId); + TInt DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId); + TInt GetResolutions(); + TInt SetResolution(TSize* aSize); + TInt GetResolution(TSize* aSize); + TInt GetTwips(TSize* aSize); + TInt GetIndexForSize(const TSize& aSize,TInt& aSpinnerOut); + TInt GetPixelFormats(); + TInt SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat); + TInt NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat, + RDisplayChannel::TBufferFormatContext* aContext); + TInt NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat, + RDisplayChannel::TBufferFormatContext* aContext); + TInt ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat, + const RDisplayChannel::TResolution& aResolution); +private: + // Constants + enum {KDfcPriority = 6}; + + enum {KBufferNotSet = -1}; + + // Buffer index points. The legacy buffer is first, followed by the user + // buffers, followed by a variable number of composition buffers. + enum { KLegacyBuffer = 0}; + enum { KFirstUserBuffer = KLegacyBuffer + 1}; + enum { KFirstCompositionBuffer = KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers}; + enum { KMaxBufferSizeHeightAndWidth = KMaxTInt16 }; + +private: + TInt iScreenNumber; + TThreadMessage* iMsg; + TInt iVSyncTicks; // Number of nanokernel ticks between frames + TUint iNumCompositionBuffers; // Number of composition buffers + TUint iTotalBuffers; // KFirstCompositionBuffer + iNumCompositionBuffers + RDisplayChannel::TDisplayInfo iChannelInfo; + RDisplayChannel::TPostCount iPostCount; // Count of Post... calls + RDisplayChannel::TPostCount iLastPostCount; // Value of iPostCount when last buffer was actually posted + TBufferInfo* iBuffer; // Allocated to contain iTotalBuffers + TBufferAddressA* iChunks; + DThread* iClient; + + // Posting support + NTimer iVSync; // Emulated VSync signal using a timer + TDfc iVSyncDfc; // DFC queued on DfcQue0 when iVSync triggers + RDisplayChannel::TBufferId iPostedBuffer; // Index of buffer to be posted on next frame + RDisplayChannel::TDisplayRotation iCurrentRotation; // Rotation of buffer being posted + RDisplayChannel::TDisplayRotation iNewRotation; // Rotation of buffer being posted + TSize iCurrentResolution; // Display resolution (normal rotation) to be posted + TSize iNewResolution; // Display resolution (normal rotation) for buffer being posted + TSize iCurrentTwips; + TInt iPostedRectCount; // Number of rectangles defined in region + RECT iPostedRect[RDisplayChannel::TDisplayInfo::KMaxRectangles]; // + + // Paint support + HWND iHwnd; // Window to be painted + RDisplayChannel::TBufferId iDisplayBuffer; // Index of buffer to be painted + RDisplayChannel::TDisplayRotation iDisplayRotation; // Rotation of buffer to be painted + TSize iDisplayResolution; // Display resolution (normal rotation) on screen + + // GetCompositionBuffer support + TUint iGetBuffer; // Index of next composition buffer + + // WaitForPost support + RDisplayChannel::TPostCount iWaitForPost; // Post count being awaited + TRequest iWaitForPostRequest; // Request to complete when post count reached + + // WaitForDisplayConnect support + TRequest iWaitForDisplayConnect; // Request to complete when display connection state changes + + TInt iDisplayStateSpinner; + + TVersion iVersion; + const RDisplayChannel::TPixelFormat* iPixelFormatArray; + TInt iPixelFormatArraySize; + RDisplayChannel::TBufferFormat iInitialBufferFormat; + RDisplayChannel::TBufferFormat iCurrentBufferFormat; + RDisplayChannel::TBufferFormat iDisplayBufferFormat; + RDisplayChannel::TBufferFormat iNewBufferFormat; + }; + +inline TBool DDisplayChannel::IsCompositionBuffer(RDisplayChannel::TBufferId aId) + { return (aId >= KFirstCompositionBuffer && aId < iTotalBuffers); } +inline TBool DDisplayChannel::IsLegacyBuffer(RDisplayChannel::TBufferId aId) + { return (aId == KLegacyBuffer); } +inline TBool DDisplayChannel::IsUserBuffer(RDisplayChannel::TBufferId aId) + { return (aId >= KFirstUserBuffer && aId < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers)); } +inline TBool DDisplayChannel::IsValidBuffer(RDisplayChannel::TBufferId aId) + { return (aId >= 0 && aId < iTotalBuffers); } +inline RDisplayChannel::TBufferId DDisplayChannel::NextCompositionBuffer(RDisplayChannel::TBufferId aId) + { TUint r = (aId + 1); return (r >= iTotalBuffers) ? KFirstCompositionBuffer : r; } + +inline TBool DDisplayChannel::IsFlipped(RDisplayChannel::TDisplayRotation aRotation) + { return !(aRotation & (RDisplayChannel::ERotationNormal | RDisplayChannel::ERotation180)); } + +#endif + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/display_dev.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/display_dev.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,39 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// + +/** + @file + @publishedPartner + @prototype +*/ + +#ifndef __DISPLAY_DEV_H__ +#define __DISPLAY_DEV_H__ + +/** + Logical Device (factory class) for display +*/ +class DDisplayDevice : public DLogicalDevice + { +public: + DDisplayDevice(); + ~DDisplayDevice(); + TInt Install(); + void GetCaps(TDes8& aDes) const; + TInt Create(DLogicalChannelBase*& aChannel); + }; + +#endif + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/displayhandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/displayhandler.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,48 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// + +/** + @file + @publishedPartner + @prototype +*/ + +#ifndef __DISPLAYHANDLER_H__ +#define __DISPLAYHANDLER_H__ + +/** +Display request handler interface +*/ +class MDisplayHandler + { +public: + /** + Process a request on this logical channel. + + @param aReqNo Request number: + == KMaxTInt, a 'DoCancel' message + >= 0, a 'DoControl' message with function number equal to aReqNo + < 0, a 'DoRequest' message with function number equal to ~aReqNo + @param a1 First argument. For DoRequest requests this is a pointer to + the TRequestStatus. + @param a2 Second argument. For DoRequest this is a pointer to the 2 + actual TAny* arguments. + @return Result. Ignored by device driver framework for DoRequest requests. + */ + virtual TInt HandleRequest(TInt aReqNo, TAny* a1, TAny* a2) = 0; + }; + +#endif + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/gui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/gui.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,523 @@ +// 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 "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: +// wins\inc\gui.h +// +// + +#ifndef __EX_GUI_H__ +#define __EX_GUI_H__ + +#define _CRTIMP // we want to use the win32 static runtime library + +#include "platform.h" +#include +#include "nk_priv.h" +#include "vwins.h" +#include +#include +#include +#include + +GLREF_C const char* skipws(const char* aPtr); +GLREF_C const char* skiptok(const char* aPtr); + +// keyboard mapping + +const TUint KKeyExtendedBit=0x100; +const TUint KKeyNormalBits=0xFF; +const TInt KMaxExtendedKey=0x5d; +const TInt KExtendedKeyBase=0x1c; +const TInt KStandardKeyMapSize = 89; +const TInt KExtendedKeyMapSize = KMaxExtendedKey + 1 - KExtendedKeyBase; +const TUint KMaxHotKeyCombinationLength=10; +const TInt KDatFileVersion= 1000; + +enum TEmulCommand + { + ENoCommand, + EKey, + ENextConfig, + ESelectConfig, + }; + +class VirtualKey + { +public: + VirtualKey(const TInt aCommandData, TEmulCommand aCommand); + virtual TBool Contains(TInt aX, TInt aY) const = 0; + virtual void Draw(HDC aHdc,COLORREF aColor) const =0; + inline TInt Value() const {return iData;}; + inline TEmulCommand Command() const {return iCommand;}; +private: + TEmulCommand iCommand; + TInt iData; + }; + +typedef TStdScanCode KeyArray[KMaxHotKeyCombinationLength]; +class KeyCombination + { +public: + KeyCombination(const TInt aCommandData, TEmulCommand aCommand); + TBool AddKey(TStdScanCode); + TBool CheckCombinationPressed(); + + TEmulCommand iCommand; + TInt iData; +private: + KeyArray iCombination; + }; + +class VKRect : public VirtualKey + { +public: + VKRect(const TInt aCommandData, TEmulCommand aCommand, TInt aX, TInt aY, TInt aWidth, TInt aHeight); + // From VirtualKey + TBool Contains(TInt aX, TInt aY) const; + virtual void Draw(HDC aHdc,COLORREF aColor) const; +private: + TInt iLeft,iTop,iRight,iBottom; + VKRect(); + }; + + + +class Alias + { +public: + Alias(); +// + TInt Add(const TDesC8& aAlias, const TDesC8& aName); + const TDesC8* operator[](const TDesC8& aAlias); +private: + struct SEntry + { + TDesC8* iAlias; + TDesC8* iName; + }; + static TBool Compare(const SEntry& aLhs, const SEntry& aRhs); +private: + RArray iMap; + }; + +// GUI settings + +const TInt KPowerTimerId=1; + +const TInt KRomMajorVersionNumber=1; +const TInt KRomMinorVersionNumber=0; +const TInt KRomBuildVersionNumber=1; +// +const TInt KScreenOffsetX=90; +const TInt KScreenOffsetY=51; +const TInt KScreenWidth=640; +const TInt KScreenHeight=240; +const TInt KWinPosX=10; +const TInt KWinPosY=10; + +const TInt KCompositionBuffers=2; // Default to double-buffering +const TInt KRefreshRateHz=30; // Default to 30fps + +const TInt KMaxNameSize=80; //size of window title string + +// +// window style +const DWORD KInvisibleControlWinStyle=WS_CAPTION|WS_CLIPCHILDREN|WS_MINIMIZEBOX|WS_OVERLAPPED|WS_SYSMENU; +const DWORD KControlWinStyle=KInvisibleControlWinStyle|WS_VISIBLE; + +const DWORD KInvisibleWinStyle=WS_CAPTION|WS_CLIPCHILDREN|WS_OVERLAPPED|WS_HSCROLL|WS_VSCROLL|WS_SIZEBOX| + WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_SYSMENU; +const DWORD KWinStyle=KInvisibleWinStyle|WS_VISIBLE; +// +// Scaling factors to use if PhysicalScreenWidth or Height are not specified +const TReal KDefaultPixelsToTwipsX=11.90625; +const TReal KDefaultPixelsToTwipsY=11.9083333334; +// +const TInt KHeapSize=0x2000; +const TInt KWindowServerHeapSize=0x40000; +const TInt KKeyDown=0x80; +// +const TInt KLedTop=45; +const TInt KLedLeft=36; +const TInt KLedSize=14; +const TInt KLedGap=5; +const TBool KLedVertical=ETrue; + +GLREF_C TInt MultiProperty(TInt (*aHandler)(TAny* aObj, const char*), TAny* aPtr, const char* aProperty); + +const TInt KSecureLedColor = 0xFFFF; + +class DWinsKeyboard : public DBase + { +public: + DWinsKeyboard(); + TInt Init(TInt aId); +// + TInt ScanCodeToRemappedKey(TInt aScanCode); + static TInt ScanCodeToStandardKey(TInt aScanCode); +// + TInt GetEPOCKeyCode(const TDesC8& aStr); + TInt GetScanCode(const TDesC8& aStr); +private: + static TInt ScanCodeToKey(TInt aScanCode, const TUint8* aStandardMap, const TUint8* aExtendedMap); + TInt DefineAlias(const char* aValue); + static TInt DoDefineAlias(TAny* aObj, const char* aValue); + TInt MapKey(const char* aValue); + static TInt DoMapKey(TAny* aObj, const char* aValue); +private: + TUint8 iStandardKeyMap[KStandardKeyMapSize]; + TUint8 iExtendedKeyMap[KExtendedKeyMapSize]; + TUint8 iAltStandardKeyMap[KStandardKeyMapSize]; + TUint8 iAltExtendedKeyMap[KExtendedKeyMapSize]; + TUint8 iCtrlStandardKeyMap[KStandardKeyMapSize]; + TUint8 iCtrlExtendedKeyMap[KExtendedKeyMapSize]; + Alias iAliasedKeys; + }; + +struct TWindowState + { +public: + WINDOWPLACEMENT iWinPlace; + TInt iXoffset; + TInt iYoffset; + TEmulatorFlip iFlipstate; + }; + +class DScreenProperties; +class TViewport + { +public: + TViewport(); + TViewport(DScreenProperties* aScreenProps); + ~TViewport(); + + void UpdateScrollBarH(HWND aHwnd); + void UpdateScrollBarV(HWND aHwnd); + + TInt GetMaxWindowWidth() const; + TInt GetMaxWindowHeight() const; + TInt GetMaxWidth() const; + TInt GetMaxHeight() const; + + TInt GetViewportOffsetX() const; + TInt GetViewportOffsetY() const; + + void SetViewportWidth(TInt aWidth); + void SetViewportHeight(TInt aHeight); + TInt GetViewportWidth() const; + TInt GetViewportHeight() const; + + void ScrollToY(TInt aPosition,HWND aHwnd); + void ScrollToX(TInt aPosition, HWND aHwnd); + + void UpdateChildPos(HWND aHwnd); + +private: + + void SetViewportOffsetX(TInt aOffset); + void SetViewportOffsetY(TInt aOffset); + + /** + The DScreenProperties object which owns this viewport + */ + DScreenProperties* iScreenProps; + + /** + Width in pixels of the client area of the window through which the emulator is being viewed + */ + TInt iViewportWidth; + /** + Height in pixels of the client area of the window through which the emulator is being viewed + */ + TInt iViewportHeight; + /** + X Offset of viewport edge from emulator image ie. How far viewport is translated + */ + TInt iViewportOffsetX; + /** + Y Offset of viewport edge from emulator image ie. How far viewport is translated + */ + TInt iViewportOffsetY; + + }; + +class DScreenProperties + { +friend class TViewport; +public: + DScreenProperties(); + ~DScreenProperties(); + TInt SetupProperties(TInt aConf, TInt aScreen); + TWindowState GetWindowState(); +public: + TInt iScreenWidth; + TInt iScreenHeight; + TInt iMaxScreenWidth; + TInt iMaxScreenHeight; + TInt iXYInputWidth; + TInt iXYInputHeight; + TInt iPhysicalScreenWidth; + TInt iPhysicalScreenHeight; + TInt iMaxPhysicalScreenWidth; + TInt iMaxPhysicalScreenHeight; + TInt iScreenOffsetX; + TInt iScreenOffsetY; + TUint iColorDepth; /// iPointerType; + TXYInputType iXYInputType; + CHAR iSysIniFileName[MAX_PATH]; + WINDOWPLACEMENT iWinPlace; + RPointerArray iVirtualKeys; + RPointerArray iControlHotKeys; + TInt iDigitizerWidth; + TInt iDigitizerHeight; + TInt iDigitizerOffsetX; //offset from the epoc screen 0! + TInt iDigitizerOffsetY;//offset from the epoc screen 0! + TBool iDigitizerEnabled; + CHAR iWindowTitle[KMaxNameSize+1]; + TBool iDisplayVersionInfo; + TInt aId; //configuration number; + TInt iInitialFlipMsg; + TBool iProcessingVirtualKey; + TUint iFakedVirtualKey; + TEmulCommand iVirtualKeyCommand; + RPointerArray iScreens; +private: + TBool iMultiTouchEnabled; + TBool iGCEEnabled; + TInt iMultiTouchProximityStep; + TInt iMultiTouchPressureStep; + }; + +struct TBufferAddressA + { + DChunk* iChunk; + TAny* iAddress; + }; + +class TScreenBuffer + { +public: + RPointerArray iFrameBuffers; + RPointerArray iMemChunks; + TInt iDisplayBufferOffset; //offset to pixel data in current mode for display buffer. Mode of display buffer doesn't change we presume! + }; + + +// Chunk cleanup object - used to clean up the process/addr table when the process goes away. +class TChunkCleanup : public TDfc + { +public: + TChunkCleanup(DProcess* aProcess, TInt aScreenNumber); + void Cancel(); + inline void SetIndex(TUint aIndex) { iIndex = aIndex; } +private: + static void ChunkDestroyed(TChunkCleanup* aSelf); +private: + DProcess* iProcess; + TInt iScreenNumber; + TInt iIndex; + }; + + +// Entry to hold the process/disp.memory address, as we need to find the address of the display +// memory when requested. A new entry would be added when a process first requests the address of display +// memory. When the process dies, we remove the process entry (by way of a DFC for a chunk that is +// created on behalf of that process). +class TProcessAddrEntry + { +public: + TProcessAddrEntry(DProcess *aProcess, TUint8* aAddress); +public: + DProcess* iProcess; + TUint8* iAddress; + }; + + + +class TBufferSet + { +public: + TAny* iDisplayBuffer; //current display buffer + BITMAPV4HEADER iInfo; // This can be cast to a BITMAPINFOHEADER + TInt iDisplayDriverCount; + TScreenBuffer iScreenBuffer; + TScreenBuffer iDsaBuffer; + RArray iProcAddrTable; + TInt iDisplayState; + TInt iStateChangeCount; + RDisplayChannel::TBufferFormat iBufferFormat; + DDisplayChannel* iDisplayChannel; + }; + +class DMasterIni : public DBase + { +public: + TInt SetupProperties(); + TInt Create(); + static TInt DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2); + TInt HalFunction(TInt aDeviceNumber, TInt aFunction, TAny* a1, TAny* a2); + static TInt DoXYHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2); + TInt XYHalFunction(TInt aFunction, TAny* a1, TAny* a2); + static TInt DoMouseHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2); + TInt MouseHalFunction(TInt aFunction, TAny* a1, TAny* a2); + static TInt DoKbdHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2); + + void InitBitmapHeader(DScreenProperties& aScreenProperties, LPBITMAPV4HEADER aInfo); + void InitBufferFormat(DScreenProperties& aScreenProperties, RDisplayChannel::TBufferFormat& aBufferFormat); + TInt AllocateFrameBuffers(TInt aScreenNumber, TInt aCount, TInt aSize); + void ReleaseFrameBuffers(TInt aScreenNumber); + + + TInt DisplayMemoryAddress(TInt aScreenNumber, TInt& aAddress); + TInt DisplayMemoryHandle(TInt aScreenNumber, TInt& aHandle); + + void ProcessDeletedDFC(); + + void SetDisplaySize(TInt aDisplayNumber, TInt aWidth, TInt aHeight); + void SetBufferFormat(TInt aDisplayNumber, TUint aAgregatSize, RDisplayChannel::TPixelFormat aPixelFormat); + void SetImageSize(TInt aScreenNumber); + +public: + //not set or used: TInt iConfigurationCount; + RPointerArray iSystemInis; //Indexed by config + RArray iBufferSet; + // Fast mutex used to control access to the process/address table in the + // TBufferSet. + NFastMutex iLock; + TUint iMaxSizeInBytes; + static const RDisplayChannel::TPixelFormat iSupportedPixelFormatTable[]; + static const TInt iSupportedPixelFormatTableSize; +private: + TInt NumberOfResolutions(TInt aDeviceNumber, TAny* a1, TAny* a2); + TInt SpecificScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* a2); + TInt CurrentScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* a2); +}; + + +GLREF_C TInt CompareI(const TDesC8& aLhs, const TDesC8& aRhs); + +// user-defined messages ... +// flip the emulator window +#define WM_FLIP_MESSAGE 0x7FFF +// emulator window power state +#define WM_EMUL_POWER_ON 0x7FFE + +//redraw client window from the internal buffer +#define WM_REDRAW_WINDOW (WM_USER + 1) + +// Set the display frame buffer for this window to lParam +#define WMU_SET_DISPLAY_BUFFER (WM_USER + 2) + +// Set the display size for this window to (wParam,lParam) +// Rotation (flip) is ignored. Current display state is used. +// Configurations are searched to find a match, message is ignored if none found. +#define WMU_SET_DISPLAY_SIZE (WM_USER + 3) + +//modifies the header of the bitmap that is getting painted, updating the size +#define WMU_SET_BUFFER_FORMAT (WM_USER + 4) + +enum TGuiPanic + { + EGuiGetModuleHandle=21, + EGuiRegisterWindow=22, + EGuiKernelWindowCreate=23, + EGuiRegisterChildWindow=24, + EGuiKernelChildWindowCreate=25, + EGuiCreateBitmap=26, + EGuiChildWinProc=27, + EGuiEnterCS=28, + EGuiLeaveCS=29, + EGuiStandbyWhilstOff=30, + EGuiResetPowerEvent=31, + EGuiSetPowerEvent=32, + EGuiWaitPowerOnFailed=33, + EGuiNoDisplayChannel=34, + EGuiVideoInfoUnavailable=35, + EGuiInvalidMultiTouch=36 + }; + +GLREF_C void Fault(TGuiPanic aPanic); + +#endif diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/mconf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/mconf.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,39 @@ +// 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 "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: +// wins\inc\mconf.h +// Brutus Persistent Machine Configuration +// +// + +#ifndef __MCONF_H__ +#define __MCONF_H__ +#include + +class TWinsMachineConfig : public TMachineConfig + { +public: + TSoundInfoV1 iSoundInfo; + TOnOffInfoV1 iOnOffInfo; + TTimeK iMainBatteryInsertionTime; + Int64 iMainBatteryInUseMicroSeconds; + Int64 iExternalPowerInUseMicroSeconds; + Int64 iMainBatteryMilliAmpTicks; + }; + +typedef TWinsMachineConfig TActualMachineConfig; + +inline TActualMachineConfig& TheActualMachineConfig() + {return (TActualMachineConfig&)Kern::MachineConfig();} + +#endif diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/monitors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/monitors.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,78 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\inc\monitors.h +// Declare stuff we need for multiple monitor support. +// (Not available in the version of windows.h we use.) +// +// + +#ifndef __MONITORS_H__ +#define __MONITORS_H__ + +#ifndef SM_CMONITORS + +#ifdef __cplusplus +extern "C" { +#endif + +#define SM_XVIRTUALSCREEN 76 +#define SM_YVIRTUALSCREEN 77 +#define SM_CXVIRTUALSCREEN 78 +#define SM_CYVIRTUALSCREEN 79 +#define SM_CMONITORS 80 +#define SM_SAMEDISPLAYFORMAT 81 + +DECLARE_HANDLE(HMONITOR); + +typedef struct tagMONITORINFO +{ + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; +} MONITORINFO, *LPMONITORINFO; + +#ifdef __cplusplus +} +#endif + +#endif // ifndef SM_CMONITORS + +/* CodeWarrior include files have SM_CMONITORS defined unconditionally, + * but MONITOR_DEFAULTTONULL etc depend upon _WIN32_WINDOWS values. + */ +#ifndef MONITOR_DEFAULTTONULL + +#define MONITOR_DEFAULTTONULL 0x00000000 +#define MONITOR_DEFAULTTOPRIMARY 0x00000001 +#define MONITOR_DEFAULTTONEAREST 0x00000002 + +#endif // ifndef MONITOR_DEFAULTTONULL + +class SystemMonitors + { +public: + SystemMonitors(void); + inline TInt Count(void) { return iCount; }; + TBool RectAllOnOne(RECT& rect); + HMONITOR MonitorFromRect(const RECT& rect, UINT flags=MONITOR_DEFAULTTONULL); + TBool GetMonitorInfo(HMONITOR monitor, LPMONITORINFO pMonInfo); +private: + TBool iHaveMultiMonFunctions; + TBool iCount; + HMONITOR (WINAPI *ipMonitorFromRect)(LPCRECT lprcScreenCoords, UINT uFlags); + BOOL (WINAPI *ipGetMonitorInfo)(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo); + }; + +#endif // ifndef __MONITORS_H__ diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/nand_fbr_offset.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/nand_fbr_offset.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,30 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\inc\NAND_FBR_OFFSET.H +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +#ifndef __NAND_FBR_OFFSET_H__ +#define __NAND_FBR_OFFSET_H__ + +/** +Defines the sector offset at which the FBR appears in the first block +@publishedPartner +*/ +const TInt KNandFbrSectorOffset=0; + +#endif diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/nand_plat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/nand_plat.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,52 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\NAND_PLAT.H +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +#ifndef __NAND_PLAT_H__ +#define __NAND_PLAT_H__ + +#include +#include + +/** +This table contains a list of all of the NAND flash devices currently +supported by the NAND flash solution. +@internalTechnology +*/ +const TNandDeviceInfo gDeviceTable[] = { + { ESamsungId, 0x73, 1024, 32, 512, 16, 9, 14, 20, 5, 0, 6, TDeviceFlags(0) }, // 16MB + // Last entry + { TManufacturerId(0), 0, 0, 0, 0, 0, 0, 0, TDeviceFlags(0) } + }; + +/** +Defining __USE_CUSTOM_ALLOCATOR enables the use of the NAND Flash Allocator. +@internalTechnology +*/ +#define __USE_CUSTOM_ALLOCATOR + +/** +The following constants support relocation of the NAND FBR for this platform +KNandFbrSectorOffset is the third of three constants required - it is defined in nand_fbr_offset.h +@publishedPartner +*/ +const TInt KNandMinibootUsed = ETrue; +const TInt KNandCoreldrRelocatable = ETrue; + +#endif diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/variant.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/variant.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,192 @@ +// 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 "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: +// wins\inc\variant.h +// Wins Variant Header +// +// + +#ifndef __VA_STD_H__ +#define __VA_STD_H__ + +#include +#include "vwins.h" +#include "nk_priv.h" +#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union +#include +#pragma warning(default : 4201) +#include + +#ifdef _DEBUG +const TInt KDefaultDebugMask = 1< +#include "nk_priv.h" + +const TUint KDefaultColorDepth = 0xffffffffu; +const TUint KDefaultColorDepthGCE = 24; + +class DDisplayChannel; + +class DWinsUiBase : public DBase + { +public: + virtual TUint ColorDepth(TInt aScreenNumber) =0; + virtual TInt SetFlip(TEmulatorFlip aFlip, TInt aScreenNumber) =0; + virtual void Info(TVariantInfoV01& aInfo) =0; + virtual HWND HWnd() =0; + virtual TInt NumberOfScreens() =0; + virtual TInt SetDisplayChannel(TInt aScreenNumber, DDisplayChannel* aDisplay) = 0; +protected: + IMPORT_C DWinsUiBase(); + }; + +#endif diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/inc/winsgui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/inc/winsgui.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,37 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\inc\winsgui.h +// +// WARNING: This file contains some APIs which are internal and are subject +// to change without notice. Such APIs should therefore not be used +// outside the Kernel and Hardware Services package. +// + +#ifndef __WINSGUI_H__ +#define __WINSGUI_H__ + +#include + +class WinsGui + { +public: + /** + Returns the current emulator GUI configuration + @publishedPartner + */ + IMPORT_C static TInt CurrentConfiguration(); + }; + + +#endif //__WINSGUI_H__ diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/medlfs.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/medlfs.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,47 @@ +// 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 "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: +// wins/medlfs.mmp +// +// + +#include "kernel/kern_ext.mmh" + +USERINCLUDE inc +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + + +target medlfs.pdd +targettype pdd + +sourcepath ../../../kernelhwsrv/kernel/eka/drivers/medlfs +source flash_media.cpp + +sourcepath specific +source lffsdev.cpp + +library elocd.lib emulator.lib + +epocallowdlldata + +start wins + +win32_library kernel32.lib +#if defined(VC32) +win32_library msvcrt.lib +#endif +end + +capability all + +VENDORID 0x70000001 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/serialldd.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/serialldd.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,47 @@ +// 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 "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: +// wins/winscomm.mmp +// ecomm.ldd Serial port logical device driver +// +// + +/** + @file +*/ + + +#include "kernel/kern_ext.mmh" +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + +SYMBIAN_BASE_SYSTEMINCLUDE(wins) + +target ecomm.ldd +targettype ldd + + + +sourcepath specific +source serialldd.cpp + +start wins +baseaddress 0x59000000 +win32_library kernel32.lib +end + +epocallowdlldata + + +capability all + +VENDORID 0x70000001 diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/serialpdd.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/serialpdd.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,44 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/ecdrv.mmp +// +// + +#include "kernel/kern_ext.mmh" +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + +SYMBIAN_BASE_SYSTEMINCLUDE(wins) + +target ecdrv.pdd + +targettype pdd + + +sourcepath specific +source serialpdd.cpp + + +library emulator.lib + +start wins +baseaddress 0x59000000 +win32_library kernel32.lib +end + +uid 0x100039d0 +VENDORID 0x70000001 + +epocallowdlldata + +capability all diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/soundsc.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/soundsc.mmp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,47 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins/soundsc.mmp +// soundsc.pdd Shared chunk sound physical device driver. +// +// + +/** + @file +*/ + +#include "kernel/kern_ext.mmh" + +USERINCLUDE inc +SYMBIAN_BASE_SYSTEMINCLUDE(drivers) + +target soundsc.pdd +targettype pdd + +sourcepath specific +source soundsc_tx.cpp +source soundsc_rx.cpp + +library emulator.lib + +uid 0x100039d0 0x1000015c +VENDORID 0x70000001 + +start wins +baseaddress 0x5a000000 +win32_library kernel32.lib winmm.lib +end + +capability all + + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/display_chan.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/display_chan.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,1554 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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 +#include +#include +#include +#include "gui.h" +#include "display_chan.h" + +#define WIN32_LEAN_AND_MEAN +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union +#include +#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union + +#ifndef DD_TRACE +#ifdef DD_TRACE_ENABLED +#define DD_TRACE(X) X +#else +#define DD_TRACE(X) +#endif +#endif + + + +DDisplayChannel::DDisplayChannel() : + iVSync(&DDisplayChannel::VSyncTimerFn, this), + iVSyncDfc(&DDisplayChannel::VSyncDfcFn, this, Kern::DfcQue0(), KDfcPriority), + iPostedBuffer((TUint)KBufferNotSet), + iGetBuffer((TUint)KFirstCompositionBuffer), + iDisplayStateSpinner(0), + iVersion(KDisplayChMajorVersionNumber, + KDisplayChMinorVersionNumber, + KDisplayChBuildVersionNumber) + { + DD_TRACE(Kern::Printf("DDisplayChannel Creation");) + } + + +DDisplayChannel::~DDisplayChannel() + { + DD_TRACE(Kern::Printf("DDisplayChannel Destruction");) + //clean up. + + NKern::ThreadEnterCS(); + Kern::Free(iBuffer); + NKern::ThreadLeaveCS(); + + } + + +/** + Second stage constructor called by the kernel's device driver framework. + This is called in the context of the user thread (client) which requested the creation of a Logical Channel + (E.g. through a call to RBusLogicalChannel::DoCreate) + The thread is in a critical section. + + @param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate + @param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate + @param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate + + @return KErrNone if successful, otherwise one of the other system wide error codes. +*/ +TInt DDisplayChannel::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer) + { + // Check version + if (!Kern::QueryVersionSupported(iDevice->iVersion, aVer)) + { + return KErrNotSupported; + } + + iScreenNumber = aUnit; /*aUnit?*/ + SetDfcQ(Kern::DfcQue0()); + iMsgQ.Receive(); + + // Ask the GUI code to initialize the rest of the object. + return Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel, + (TAny*)iScreenNumber, this); + } + + +void DDisplayChannel::ValidateSpecificInfo(TInt aBytesPerPixel, RDisplayChannel::TOrientationSpecificInfo& aInfo) + { + __ASSERT_DEBUG(aInfo.iWidth > 0 && aInfo.iHeight > 0, Panic(EDisplayPanicInvalidDimensions)); + __ASSERT_DEBUG(aInfo.iOffsetBetweenLines > 0, Panic(EDisplayPanicInvalidStride)); + __ASSERT_DEBUG(aInfo.iWidth * aBytesPerPixel <= (TUint)aInfo.iOffsetBetweenLines, Panic(EDisplayPanicInvalidStride)); + + //this is just to stop compiler complaining.. + (TAny)aBytesPerPixel; + (TAny)aInfo; + } + +/** +Finish creating the display channel object. + +@param aInfo Display description object +@param aRotation Initial rotation +@param aHwnd Associated window handle +@param aFrameBuffers Array of one or more pointers to frame buffers +@param aResolution Initial resolution +@param aTwips Size in twips +@return KErrNone if successful, or a system-wide error otherwise. +*/ +TInt DDisplayChannel::Initialize(RDisplayChannel::TDisplayInfo& aInfo, + RDisplayChannel::TDisplayRotation aRotation, + HWND aHwnd, RPointerArray& aFrameBuffers, + RPointerArray& aChunks, + TScreenBuffer& aDsaBuffer, + TSize aResolution, + TSize aTwips, + const RDisplayChannel::TPixelFormat aPixelFormatArray[], + const TInt aPixelFormatArraySize, + const RDisplayChannel::TBufferFormat& aBufferFormat) + + { + __ASSERT_DEBUG(aInfo.iBitsPerPixel >= 12 && aInfo.iBitsPerPixel <= 32, Panic(EDisplayPanicInvalidBitDepth)); + __ASSERT_DEBUG(aInfo.iRefreshRateHz > 0, Panic(EDisplayPanicInvalidRefreshRate)); + __ASSERT_DEBUG(aInfo.iAvailableRotations & aRotation, Panic(EDisplayPanicInvalidRotation)); + __ASSERT_DEBUG(aInfo.iNormal.iWidth == aInfo.iFlipped.iHeight, Panic(EDisplayPanicInvalidDimensions)); + __ASSERT_DEBUG(aInfo.iNormal.iHeight == aInfo.iFlipped.iWidth, Panic(EDisplayPanicInvalidDimensions)); + __ASSERT_DEBUG(aRotation == RDisplayChannel::ERotationNormal || + aRotation == RDisplayChannel::ERotation90CW || + aRotation == RDisplayChannel::ERotation180 || + aRotation == RDisplayChannel::ERotation270CW, Panic(EDisplayPanicInvalidRotation)); + __ASSERT_DEBUG(aFrameBuffers.Count() > 0, Panic(EDisplayPanicInvalidFrameBuffers)); + __ASSERT_DEBUG(aHwnd, Panic(EDisplayPanicInvalidWindowHandle)); + + ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iNormal); + ValidateSpecificInfo((aInfo.iBitsPerPixel > 16) ? 4 : 2, aInfo.iFlipped); + + // aFrameBuffers includes the legacy buffer at index 0. + iNumCompositionBuffers = aFrameBuffers.Count() - 1; + iTotalBuffers = KFirstCompositionBuffer + iNumCompositionBuffers; + iBuffer = (TBufferInfo*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferInfo)); + iChunks = (TBufferAddressA*)Kern::AllocZ(iTotalBuffers * sizeof(TBufferAddressA)); + if (!iBuffer) + { + return KErrNoMemory; + } + + aInfo.iNumCompositionBuffers = iNumCompositionBuffers; + for (TUint index = 0; index < iNumCompositionBuffers; index++) + { + iBuffer[index + KFirstCompositionBuffer].iAddress = aFrameBuffers[index + 1]; + iChunks[index + KFirstCompositionBuffer].iChunk = aChunks[index + 1]->iChunk; + } + + iChannelInfo = aInfo; + + iDisplayRotation = iCurrentRotation = aRotation; + iDisplayResolution = iCurrentResolution = aResolution; + iCurrentTwips = aTwips; + iHwnd = aHwnd; + + // Ensure the VSync DFC is on the same queue as the message handling. + iVSyncTicks = NKern::TimerTicks(1000 / aInfo.iRefreshRateHz); + iVSync.OneShot(iVSyncTicks); + + if (aDsaBuffer.iMemChunks.Count() != 0) + { + iBuffer[KLegacyBuffer].iAddress = aDsaBuffer.iFrameBuffers[0]; + } + else + { + iBuffer[KLegacyBuffer].iAddress = NULL; + } + + iPixelFormatArray = aPixelFormatArray; + iPixelFormatArraySize = aPixelFormatArraySize; + + // copy the initial buffer format + iInitialBufferFormat = aBufferFormat; + iDisplayBufferFormat = iInitialBufferFormat; + iCurrentBufferFormat = iDisplayBufferFormat; + return KErrNone; + } + + +/** +Set the address of the legacy buffer. + +@param aAddress Pointer to the legacy buffer. +*/ +void DDisplayChannel::SetLegacyBuffer(void *aAddress) + { + iBuffer[KLegacyBuffer].iAddress = aAddress; + } + + + +/** +Handle a message on this display for the logical channel. + +@param aMsg The message to process. The iValue member of this distinguishes the + message type: + iValue == ECloseMsg, channel close message + iValue == KMaxTInt, a 'DoCancel' message + iValue >= 0, a 'DoControl' message with function number equal to iValue + iValue < 0, a 'DoRequest' message with function number equal to ~iValue +*/ +void DDisplayChannel::HandleMsg(TMessageBase* aMsg) + { + iMsg = (TThreadMessage*)aMsg; + TInt id = iMsg->iValue; + TInt r = KErrNone; + + if (id == (TInt)ECloseMsg) + { + iVSync.Cancel(); + iWaitForPostRequest.Complete(KErrCancel); + iWaitForDisplayConnect.Complete(KErrCancel); + if (iBuffer) + { + // Unhook display channel from the GUI code if initialized. + if (iBuffer[KLegacyBuffer].iAddress) + { + Kern::HalFunction(EHalGroupEmulator, EEmulatorHalSetDisplayChannel, + (TAny*)iScreenNumber, NULL); + PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0, 0); + InvalidateRect(iHwnd, NULL, FALSE); + } + + RDisplayChannel::TBufferId index = iTotalBuffers; + + while (index-- > 0) + { + iBuffer[index].iRequest.Complete(KErrCancel); + + if (IsUserBuffer(index)) + { + // Close chunk + if (iBuffer[index].iChunk) + { + NKern::ThreadEnterCS(); + Kern::ChunkClose(iBuffer[index].iChunk); + NKern::ThreadLeaveCS(); + } + } + } + + } + iMsg->Complete(KErrNone, EFalse); + return; + } + + if (id < 0) + { + DoRequest(~id); + r = KErrNone; + } + else + { + r = (id == KMaxTInt) ? DoCancel(iMsg->Int0()) : DoControl(id); + } + + iMsg->Complete(r, (id != ECloseMsg)); + } + + +/** +Process synchronous 'control' requests. Parameters are in the first two +arguments of iMsg. +*/ +TInt DDisplayChannel::DoControl(TInt aFunction) + { + DD_TRACE(Kern::Printf(">DDisplayChannel::DoControl fn=%d\n", aFunction);) + + TInt r = KErrNotSupported; + TPckgBuf pkg(iChannelInfo); + switch(aFunction) + { + case RDisplayChannel::ECtrlGetDisplayInfo: + // a1: TDisplayInfo* info [out] + Kern::KUDesPut(*(TDes8*)iMsg->Ptr0(), pkg); ///*&iChannelInfo*/); + r = KErrNone; + break; + + case RDisplayChannel::ECtrlOpen: + // Everything is done in Construct + r = KErrNone; + break; + + case RDisplayChannel::ECtrlClose: + // Nothing to do? + r = KErrNone; + break; + + case RDisplayChannel::ECtrlPostCompositionBuffer: + // a1: const TRegionFix* region [in] + // a2: TPostCount* post count [out] + r = PostCompositionBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1()); + break; + + case RDisplayChannel::ECtrlPostLegacyBuffer: + // a1: const TRegionFix* region [in] + // a2: TPostCount* post count [out] + r = PostLegacyBuffer(iMsg->Ptr0(), (RDisplayChannel::TPostCount*)iMsg->Ptr1()); + break; + + case RDisplayChannel::ECtrlRegisterUserBuffer: + // a1: { TInt Chunk handle, TInt offset }* [in] + // a2: TInt* buffer ID [out] + { + __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument)); + TInt arg[2]; + kumemget(arg, iMsg->Ptr0(), sizeof(arg)); + r = RegisterUserBuffer(arg[0], arg[1], (RDisplayChannel::TBufferId*)iMsg->Ptr1()); + } + break; + + case RDisplayChannel::ECtrlDeregisterUserBuffer: + // a1: TBufferId* buffer ID [in] + r = DeregisterUserBuffer((RDisplayChannel::TBufferId*)iMsg->Ptr0()); + break; + + case RDisplayChannel::ECtrlSetRotation: + // a1: TDisplayRotation* new rotation [in] + // a2: TBool* display config has changed [out] + r = SetRotation((RDisplayChannel::TDisplayRotation*)iMsg->Ptr0(), (TBool*)iMsg->Ptr1()); + break; + + case RDisplayChannel::ECtrlCurrentRotation: + // a1: TDisplayRotation* current rotation [out] + r = SafePut(iMsg->Ptr0(), &iCurrentRotation, sizeof(iCurrentRotation)); + break; + + case ECloseMsg: + r = KErrNone; + break; + + case RDisplayChannel::ECtrlGetCompositionBufferInfo: + { + TInt arg[2]; + TInt index = *((TInt*)(iMsg->Ptr0())); + r = Kern::MakeHandleAndOpen(iMsg->Client(), iChunks[index + KFirstCompositionBuffer].iChunk); + if(r >= 0) + { + arg[0] = r; + arg[1] = 0; + SafePut(iMsg->Ptr1(),&arg,(sizeof(TInt)*2)); + r = KErrNone; + } + } + break; + // added to v1.0 + case RDisplayChannel::ECtrlVersion: + r = SafePut(iMsg->Ptr0(), &iVersion, sizeof(iVersion)); + break; + //v1_1 + case RDisplayChannel::ECtrlNumberOfResolutions: + { + r = NumberOfResolutions(); + } + break; + case RDisplayChannel::ECtrlGetResolutions: + { + r = GetResolutions(); + if(r == KErrCorrupt) //Resolution list changed during GetResolutions + {//second go + r = GetResolutions(); + } + } + break; + case RDisplayChannel::ECtrlSetResolution: + { + r = SetResolution((TSize*)iMsg->Ptr0()); + } + break; + case RDisplayChannel::ECtrlGetResolution: + { + r = GetResolution((TSize*)iMsg->Ptr0()); + } + break; + case RDisplayChannel::ECtrlGetTwips: + { + r = GetTwips((TSize*)iMsg->Ptr0()); + } + break; + case RDisplayChannel::ECtrlNumberOfPixelFormats: + r = iPixelFormatArraySize; + break; + case RDisplayChannel::ECtrlGetPixelFormats: + r = GetPixelFormats(); + break; + case RDisplayChannel::ECtrlSetBufferFormat: + r = SetBufferFormat((RDisplayChannel::TBufferFormat*)iMsg->Ptr0()); + break; + case RDisplayChannel::ECtrlGetBufferFormat: + r = SafePut(iMsg->Ptr0(), &iCurrentBufferFormat, sizeof(iCurrentBufferFormat)); + break; + case RDisplayChannel::ECtrlNextPlaneOffset: + // we support, for moment only packed pixel formats + r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL); + break; + case RDisplayChannel::ECtrlNextLineOffset: + // use the internal current resolution and current rotation + r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), NULL); + break; + case RDisplayChannel::ECtrlNextPlaneOffsetExtended: + // we support, for moment only packed pixel formats + r = NextPlaneOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), + (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1()); + break; + case RDisplayChannel::ECtrlNextLineOffsetExtended: + r = NextLineOffset((RDisplayChannel::TBufferFormat*)iMsg->Ptr0(), + (RDisplayChannel::TBufferFormatContext*)iMsg->Ptr1()); + break; + } + DD_TRACE(Kern::Printf(" infoPckg(info); + + for (TInt res=0;resPtr0(), and the other +two parameters are in iMsg->Ptr1() and iMsg->Ptr2(). +*/ +void DDisplayChannel::DoRequest(TInt aFunction) + { + DD_TRACE(Kern::Printf(">DDisplayChannel::DoRequest fn=%d\n", aFunction);) + + TInt r = KErrNotSupported; + + switch(aFunction) + { + case RDisplayChannel::EReqGetCompositionBuffer: + // a1: TAny** buffer address [out] + r = GetCompositionBuffer(static_cast(iMsg->Ptr1())); + break; + + case RDisplayChannel::EReqPostUserBuffer: + // a1: { TBufferId* buffer ID, const TRegionFix* region }* [in] + // a2: TPostCount* post count [out] + { + TAny* arg[2]; + __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument)); + kumemget(arg, iMsg->Ptr1(), sizeof(arg)); + r = PostUserBuffer(reinterpret_cast(arg[0]), arg[1], + reinterpret_cast(iMsg->Ptr2())); + } + break; + + case RDisplayChannel::EReqWaitForPost: + // a1: TInt* post to wait for [in] + r = WaitForPost(static_cast(iMsg->Ptr1())); + break; + //v1_1 + case RDisplayChannel::EReqWaitForDisplayConnect: + r = WaitForDisplayConnect(); + break; + } + + DD_TRACE(Kern::Printf("(iMsg->Ptr0()); + Kern::RequestComplete(iMsg->Client(), status, r); + } + } + + +/** +Process asynchronous request cancellations +*/ +TInt DDisplayChannel::DoCancel(TInt aRequestMask) + { + DD_TRACE(Kern::Printf(">DDisplayChannel::DoCancel mask=%x\n", aRequestMask);) + + if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelGetCompositionBuffer)) + { + if (IsCompositionBuffer(iGetBuffer)) + { + iBuffer[iGetBuffer].iRequest.Complete(KErrCancel); + } + } + + if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelPostUserBuffer)) + { + if (IsUserBuffer(iPostedBuffer)) + { + iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel); + } + } + + if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForPost)) + { + iWaitForPostRequest.Complete(KErrCancel); + } + if (aRequestMask & (1 << RDisplayChannel::ECtrlCancelWaitForDisplayConnect)) + { + iWaitForDisplayConnect.Complete(KErrCancel); + } + + DD_TRACE(Kern::Printf("(aDisplayChannel)->DoVSyncTimer(); + } + +/** +Instance function called on the timer thread. Queues the VSyncDfc to run on its +thread. +*/ +void DDisplayChannel::DoVSyncTimer(void) + { + iVSyncDfc.Add(); + iVSync.Again(iVSyncTicks); + } + + +/** +DFC function to post the current buffer to the display. +@param aDisplayImpl The display object to be posted. +*/ +void DDisplayChannel::VSyncDfcFn(TAny* aDisplayChannel) + { + reinterpret_cast(aDisplayChannel)->DoVSync(); + } + + +/** +Post the current buffer to the display. Signal waiting threads under various +conditions. This is run off the same DFC queue as message handling, so there is +no need to protect the fields. +*/ +void DDisplayChannel::DoVSync(void) + { + if(iWaitForDisplayConnect.iStatus) + { + TInt currentSpinner; + Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, ¤tSpinner, NULL, iScreenNumber); + //display state changed + if(currentSpinner != iDisplayStateSpinner) + iWaitForDisplayConnect.Complete(KErrNone); + } + + if (IsValidBuffer(iPostedBuffer)) + { + // Complete any outstanding request for the buffer which was displayed. + // This either signifies the user or composition buffer becoming + // available + if (iDisplayBuffer != iPostedBuffer) + { + iBuffer[iDisplayBuffer].iRequest.Complete(KErrNone); + } + + iDisplayBuffer = (RDisplayChannel::TBufferId)iPostedBuffer; + iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet; + + // Update the pixel pointer used when painting the client window + PostMessage(iHwnd, WMU_SET_DISPLAY_BUFFER, 0, + (LPARAM)iBuffer[iDisplayBuffer].iAddress); + + // check if the buffer format is modified + if ((iDisplayBufferFormat.iSize.iHeight != iNewBufferFormat.iSize.iHeight) || + (iDisplayBufferFormat.iSize.iWidth != iNewBufferFormat.iSize.iWidth) || + (iDisplayBufferFormat.iPixelFormat != iNewBufferFormat.iPixelFormat)) + { + // We post in one messages everything, but we got to pack the size + // speculate that the maximum width and height can be represented in 16 bit + TUint aggregateSize = ((TUint)iNewBufferFormat.iSize.iHeight << 16) & 0xffff0000; + aggregateSize += (TUint)iNewBufferFormat.iSize.iWidth & 0x0000ffff; + PostMessage(iHwnd, + WMU_SET_BUFFER_FORMAT, + aggregateSize, + iNewBufferFormat.iPixelFormat); + iDisplayBufferFormat = iNewBufferFormat; + } + + if (iDisplayRotation != iNewRotation) + { + iDisplayRotation = iNewRotation; + + TUint flip; + switch (iDisplayRotation) + { + case RDisplayChannel::ERotation90CW: + flip = EEmulatorFlipLeft; + break; + case RDisplayChannel::ERotation180: + flip = EEmulatorFlipInvert; + break; + case RDisplayChannel::ERotation270CW: + flip = EEmulatorFlipRight; + break; + default: // Normal + flip = EEmulatorFlipRestore; + break; + } + PostMessage(iHwnd, WM_FLIP_MESSAGE, flip, NULL); + + iPostedRectCount = 0; // Force full invalidation + } + + if (iDisplayResolution.iWidth != iNewResolution.iWidth || + iDisplayResolution.iHeight != iNewResolution.iHeight) + { + iDisplayResolution = iNewResolution; + PostMessage(iHwnd, WMU_SET_DISPLAY_SIZE, + iDisplayResolution.iWidth, iDisplayResolution.iHeight); + } + + + // Invalidate the window contents where necessary + TInt count = iPostedRectCount; + if (count) + { + // Order of invalidation is immaterial + while (count--) + { + InvalidateRect(iHwnd, &iPostedRect[count], FALSE); + } + + iPostedRectCount = 0; + } + else + { + InvalidateRect(iHwnd, NULL, FALSE); + } + + // Use differences to allow for wraparound + if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0) + { + // Post waited for is now being displayed or was dropped + iWaitForPostRequest.Complete(KErrNone); + } + iLastPostCount = iPostCount; + } + } + + +/** +Set the status object for this request and the thread to complete it on, if not +already set. +@param aStatus The new request status. +@param aThread The thread on which to complete. +@return EFalse if the status is already set, or ETrue if the status has now been +set. +*/ +TBool DDisplayChannel::TRequest::SetStatus(TThreadMessage& aMsg) + { + if (iStatus) + { + __ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnSet)); + return EFalse; // In use + } + + __ASSERT_DEBUG(!iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadAlreadySet)); + DThread* thread = aMsg.Client(); + TInt r = thread->Open(); + __ASSERT_DEBUG( r == KErrNone, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicThreadOpenFailed)); + (TAny)r; + iThread = thread; + iStatus = reinterpret_cast(aMsg.Ptr0()); + return ETrue; + } + + +/** +Complete the request with the given result. If the status has not been set, or +has already been completed, this does nothing. +@param aResult The result of the asynchronous request. +*/ +void DDisplayChannel::TRequest::Complete(TInt aResult) + { + if (iStatus) + { + __ASSERT_DEBUG(iThread, Kern::PanicCurrentThread(RDisplayChannel::Name(), EDisplayPanicNullThreadOnComplete)); + Kern::RequestComplete(iThread, iStatus, aResult); + Kern::SafeClose((DObject*&)iThread, NULL); + } + } + + +/** +Post the current composition buffer to the display on the next frame tick. +@param aRegion NULL if the entire buffer has changed, or a user pointer to up +to TDisplayInfo::KMaxRectagles areas that have changed. +@param aPostCount User pointer to an integer to receive the new post count. +@return KErrNone, or a system-wide error code +*/ +TInt DDisplayChannel::PostCompositionBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount) + { + if (!IsCompositionBuffer(iGetBuffer)) + { + return KErrNotSupported; + } + + if (iWaitForPost == iPostCount) + { + // Complete wait for post (dropped) + iWaitForPostRequest.Complete(KErrNone); + } + + if (IsUserBuffer(iPostedBuffer)) + { + // Complete the user post request (not displayed) + iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel); + } + + iPostedBuffer = iGetBuffer; + iGetBuffer = NextCompositionBuffer(iGetBuffer); + + if (iNumCompositionBuffers > 2 && iGetBuffer == iDisplayBuffer) + { + // With more than two buffers, there must always be one available with + // no waiting required, so find it. + iGetBuffer = NextCompositionBuffer(iGetBuffer); + } + + // Get the region + if (aRegion) + { + // Set iPostedRect(Count) from aRegion. + Panic(EDisplayPanicNotYetImplemented); + } + + // What to do about wrapping? + iPostCount++; + iNewRotation = iCurrentRotation; + iNewResolution = iCurrentResolution; + iNewBufferFormat = iCurrentBufferFormat; + SafePut(aPostCount, &iPostCount, sizeof(iPostCount)); + + return KErrNone; + } + + +/** +Post the legacy buffer to the display on the next frame tick. +@param aRegion NULL if the entire buffer has changed, or a user pointer to up +to TDisplayInfo::KMaxRectagles areas that have changed. +@param aPostCount User pointer to an integer to receive the new post count. +@return KErrNone, or a system-wide error code +*/ +TInt DDisplayChannel::PostLegacyBuffer(TAny* aRegion, RDisplayChannel::TPostCount* aPostCount) + { + if (iWaitForPost == iPostCount) + { + // Complete wait for post (dropped) + iWaitForPostRequest.Complete(KErrNone); + } + + if (IsUserBuffer(iPostedBuffer)) + { + iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel); + } + + // iBuffer should NOT be NULL here! + __ASSERT_ALWAYS(iBuffer[KLegacyBuffer].iAddress, Panic(EDisplayPanicNoLegacyBuffer)); + iPostedBuffer = KLegacyBuffer; + + // Get the region into iRegion + if (aRegion) + { + // Set iPostedRect(Count) from aRegion. + Panic(EDisplayPanicNotYetImplemented); + } + + iPostCount++; + iNewRotation = iCurrentRotation; + iNewResolution = iCurrentResolution; + iNewBufferFormat = iCurrentBufferFormat; + SafePut(aPostCount, &iPostCount, sizeof(iPostCount)); + + return KErrNone; + } + + +/** +Asynchronously request the current composition buffer. Completes immediately +if not already being displayed, or an error occurs. +@param aStatus The request status to be completed. +@param aAddress The user pointer to the location to put the address. +*/ +TInt DDisplayChannel::GetCompositionBuffer(TAny** aAddress) + { + if (!IsCompositionBuffer(iGetBuffer)) + { + // No composition buffers available for use. + return KErrNotSupported; + } + + // The address won't change, so may as well set it now. + TUint idx = iGetBuffer - KFirstCompositionBuffer; + if (SafePut(aAddress, &idx, sizeof(TUint)) != KErrNone) + { + return KErrArgument; + } + + if (iNumCompositionBuffers > 1 && iGetBuffer == iDisplayBuffer) + { + // Multi-buffer case, and buffer is currently being displayed + + if (iBuffer[iGetBuffer].iRequest.SetStatus(*iMsg)) + { + return KRequestPending; + } + + // Already set + return KErrInUse; + } + + return KErrNone; + } + + +/** +Post a user buffer to the display on the next frame tick. +@param aBufferId The ID of the user buffer to post. +@param aRegion NULL if the entire buffer has changed, or a user pointer to up +to TDisplayInfo::KMaxRectagles areas that have changed. +@return KErrNone, or a system-wide error code +*/ +TInt DDisplayChannel::PostUserBuffer(RDisplayChannel::TBufferId* aBufferId, TAny* aRegion, RDisplayChannel::TPostCount* aPostCount) + { + RDisplayChannel::TBufferId bufferId; + bufferId = reinterpret_cast (aBufferId); + + if (!IsUserBuffer(bufferId)) + { + // Not a user buffer. + return KErrArgument; + } + + if (!iBuffer[bufferId].iChunk) + { + // User buffer not initialised. + return KErrArgument; + } + + if (iWaitForPost == iPostCount) + { + // Complete wait for post (dropped) + iWaitForPostRequest.Complete(KErrNone); + } + + if (IsUserBuffer(iPostedBuffer)) + { + // Complete the user post request (not displayed) + iBuffer[iPostedBuffer].iRequest.Complete(KErrCancel); + } + + if (bufferId == iDisplayBuffer) //pathological case + { + // Complete the current display buffer as we are superceding it with the same one + iBuffer[bufferId].iRequest.Complete(KErrNone); + } + + // Only one buffer can be posted at any time, and if it were this user + // buffer, the request will have just been completed, so this shouldn't fail. + TBool isSet = iBuffer[bufferId].iRequest.SetStatus(*iMsg); + + __ASSERT_DEBUG(isSet, Panic(EDisplayPanicInUse)); + (TAny)isSet; + iPostedBuffer = bufferId; + + // Get the region + if (aRegion) + { + // Set iPostedRect(Count) from aRegion. + Panic(EDisplayPanicNotYetImplemented); + } + + iPostCount++; + iNewRotation = iCurrentRotation; + iNewResolution = iCurrentResolution; + iNewBufferFormat = iCurrentBufferFormat; + SafePut(aPostCount, &iPostCount, sizeof(iPostCount)); + + return KRequestPending; + } + +/** +Asynchronous request notification when the given post count is reached (or +passed). +@param aStatus The request status to be completed. +@param aPostCount The count to wait for. +*/ +TInt DDisplayChannel::WaitForPost(RDisplayChannel::TPostCount* aPostCount) + { + TInt postCount; + + kumemget(&postCount, aPostCount, sizeof(RDisplayChannel::TPostCount)); + + if ((TInt)(iWaitForPost - iLastPostCount) > 0 && (TInt)(iPostCount - iWaitForPost) >= 0) + { + // Set up the request to be completed when the post occurs + if (iWaitForPostRequest.SetStatus(*iMsg)) + { + iWaitForPost = postCount; + return KRequestPending; + } + + // Already waiting for a post + return KErrInUse; + } + + // Requested post already displayed/dropped + return KErrNone; + } + +/** +Asynchronous request notification when the display connection state changes. +This occurs when the display is disconnected, connected with no list, or a list of modes becomes available or is updated. +*/ +TInt DDisplayChannel::WaitForDisplayConnect() + { + + Kern::HalFunction(EHalGroupDisplay, EDisplayHalGetStateSpinner, &iDisplayStateSpinner, NULL, iScreenNumber); + + if (iWaitForDisplayConnect.SetStatus(*iMsg)) + { + return KRequestPending; + } + + // Already waiting for a post + return KErrInUse; + } + + +/** +Set the rotation of the screen on the next frame. If the buffer contents will +not be valid, the flag set. The validity of the buffer is down to whether the +width and height change. + +@param aNewRotation Address in user space of the new rotation setting. +@param aDisplayConfigChanged Address in user space of where to put whether the +orientation specific info to use has changed following the rotation setting. +@return KErrNone, or KErrArgument if an argument was invalid. +*/ +TInt DDisplayChannel::SetRotation(RDisplayChannel::TDisplayRotation* aNewRotation, + TBool* aDisplayConfigChanged) + { + RDisplayChannel::TDisplayRotation newRotation; + + __ASSERT_DEBUG(aNewRotation, Panic(EDisplayPanicNullArgument)); + + kumemget(&newRotation, aNewRotation, sizeof(newRotation)); + + if (((TInt)newRotation - 1) & newRotation) + { + // More than one bit is set, which is not valid + return KErrArgument; + } + + if ((iChannelInfo.iAvailableRotations & newRotation) == 0) + { + // Rotation is not supported + return KErrArgument; + } + + TBool displayConfigChanged = (IsFlipped(newRotation) != IsFlipped(iCurrentRotation)); + iCurrentRotation = newRotation; + + SafePut(aDisplayConfigChanged, &displayConfigChanged, sizeof(TBool)); + + return KErrNone; + } + + +/** +Register a user buffer. Assign an ID for it (if available) and open the chunk to +get the address. +@param aChunkHandle The chunk handle. +@param aOffset The offset from the chunk base address to the start of the +buffer. +@param aBufferId The address in user space of where to put the buffer ID. +*/ +TInt DDisplayChannel::RegisterUserBuffer(TInt aChunkHandle, TInt aOffset, + RDisplayChannel::TBufferId* aBufferId) + { + if (!aBufferId) + { + return KErrArgument; + } + + NKern::ThreadEnterCS(); + DChunk* chunk = Kern::OpenSharedChunk(iMsg->Client(), aChunkHandle, + EFalse); + NKern::ThreadLeaveCS(); + if (!chunk) + { + return KErrBadHandle; + } + + TLinAddr kernelAddress; + + const TInt bufferSize = (iDisplayResolution.iWidth * iDisplayResolution.iHeight); + TInt r = Kern::ChunkAddress(chunk,aOffset,bufferSize,kernelAddress); + if(r!=KErrNone) + { + NKern::ThreadEnterCS(); + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return r; + } + + // Search for an empty slot + for (TInt index = KFirstUserBuffer; index < (KFirstUserBuffer + RDisplayChannel::TDisplayInfo::KMaxUserBuffers); index++) + { + if (!iBuffer[index].iChunk) + { + // Found one, so fill in the details and return the index as the ID. + iBuffer[index].iChunk = chunk; + iBuffer[index].iAddress = (TAny*)(kernelAddress); + kumemput(aBufferId, &index, sizeof(RDisplayChannel::TBufferId)); + return KErrNone; + } + } + + // No slots available. + NKern::ThreadEnterCS(); + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return KErrTooBig; + } + + +/** +Deregister a user buffer. +@param aBufferId The buffer ID. +*/ +TInt DDisplayChannel::DeregisterUserBuffer(RDisplayChannel::TBufferId* aBufferId) + { + RDisplayChannel::TBufferId bufferId; + + __ASSERT_DEBUG(aBufferId, Panic(EDisplayPanicNullArgument)); + kumemget(&bufferId, aBufferId, sizeof(RDisplayChannel::TBufferId)); + + if (!IsUserBuffer(bufferId)) + { + // Not a valid ID + return KErrArgument; + } + + TBufferInfo* buffer = &iBuffer[bufferId]; + if (!buffer->iChunk) + { + // Not registered + return KErrArgument; + } + + if (iDisplayBuffer == bufferId) + { + return KErrInUse; + } + + if (iPostedBuffer == bufferId) + { + // Was queued to be posted + iPostedBuffer = (RDisplayChannel::TBufferId)KBufferNotSet; + iPostedRectCount = 0; + } + + // Cancel any outstanding request on the buffer and clear out the fields. + buffer->iRequest.Complete(KErrCancel); + NKern::ThreadEnterCS(); + Kern::ChunkClose(buffer->iChunk); + NKern::ThreadLeaveCS(); + buffer->iChunk = NULL; + buffer->iAddress = NULL; + + return KErrNone; + } + +/** +Get all resolutions available for this screen and insert to a descriptor +@return KErrNone if successful, otherwise a system wide error code. +*/ +TInt DDisplayChannel::GetResolutions() + { + TInt r; + __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument)); + __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument)); + //get the number of resolutions (as above) + TInt numberOfResolutions = 0; + TInt refStateSpinner, curStateSpinner; + //Get the number of resolutions as well as the display state spinner at this point + r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, &refStateSpinner, iScreenNumber); + if(r < KErrNone) + { + return r; + } + + TInt length; + TInt maxLength; + Kern::KUDesInfo(*(const TDesC*)iMsg->Ptr0(),length,maxLength); + + if ((maxLength/static_cast(sizeof(RDisplayChannel::TResolution))) < numberOfResolutions) + { + return KErrOverflow; + } + + TVideoInfoV01 info; + TPckg infoPckg(info); + RDisplayChannel::TResolution resolution = {{0,0},{0,0},RDisplayChannel::ERotationAll}; + TPtr8 tempDes(NULL,0); + + TInt i; + for (i=0;iPtr0(),(i)*sizeof(RDisplayChannel::TResolution)); + return KErrCorrupt; + } + + //pass info package to be filled in, also sending the config to read, and the screen within that + Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber); + //save resolution + resolution.iPixelSize = info.iSizeInPixels; + resolution.iTwipsSize = info.iSizeInTwips; + //copy resolution + tempDes.Set((TUint8*)&resolution,sizeof(RDisplayChannel::TResolution),sizeof(RDisplayChannel::TResolution)); + r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(),tempDes,i*sizeof(RDisplayChannel::TResolution),iMsg->Client()); + + if (rPtr0(),(i)*sizeof(RDisplayChannel::TResolution)); + return r; + } + } + Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(),(i)*sizeof(RDisplayChannel::TResolution)); + SafePut(iMsg->Ptr1(), &numberOfResolutions, sizeof(numberOfResolutions)); + return KErrNone; + } + + + +TInt DDisplayChannel::SetResolution(TSize* aSize) + { + if (!aSize) + { + ClientPanic(RDisplayChannel::ENullArgument); + return KErrArgument; + } + + TSize size; + kumemget32(&size, aSize, sizeof(size)); + if (size.iWidth < 0 || size.iHeight < 0) + { + ClientPanic(RDisplayChannel::EInvalidResolution); + return KErrArgument; + } + + if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, + __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)"))) + { + return KErrPermissionDenied; + } + + // Validate size. Return KErrArgument on failure. + //Get the number of resolutions + TInt numberOfResolutions; + TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, &numberOfResolutions, NULL, iScreenNumber); + if(r < KErrNone) + { + return r; + } + TVideoInfoV01 info; + TPckg infoPckg(info); + for (TInt i = 0; i < numberOfResolutions; i++) + { + //pass info package to be filled in, also sending the config to read, and the screen within that + Kern::HalFunction(EHalGroupDisplay, EDisplayHalSpecificScreenInfo, &i, &infoPckg, iScreenNumber); + + if (info.iSizeInPixels.iWidth == size.iWidth && + info.iSizeInPixels.iHeight == size.iHeight) + { //matched resolution + iCurrentResolution = size; + iCurrentTwips = info.iSizeInTwips; + + if (iCurrentResolution.iHeight > iNewBufferFormat.iSize.iHeight || + iCurrentResolution.iWidth > iNewBufferFormat.iSize.iWidth) + { + // going back to initial settings and, we hope, + // the buffers could still be displayed correctly, but we have no guarantee + iCurrentBufferFormat = iInitialBufferFormat; + } + return KErrNone; + } + } + return KErrArgument; //if reached here, it did not match aSize to any config resolution + } + +TInt DDisplayChannel::GetResolution(TSize* aSize) + { + TInt numberOfResolutions; + TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, + &numberOfResolutions, NULL, iScreenNumber); + + if (r == KErrNone) + { + if (numberOfResolutions > 0) + { + SafePut(aSize, &iCurrentResolution, sizeof(iCurrentResolution)); + } + else + { + TSize resolution = {0,0}; + SafePut(aSize, &resolution, sizeof(resolution)); + } + } + return r; + } + +TInt DDisplayChannel::GetTwips(TSize* aSize) + { + TInt numberOfResolutions; + TInt r = Kern::HalFunction(EHalGroupDisplay, EDisplayHalNumberOfResolutions, + &numberOfResolutions, NULL, iScreenNumber); + + if (r == KErrNone) + { + if (numberOfResolutions > 0) + { + SafePut(aSize, &iCurrentTwips, sizeof(iCurrentTwips)); + } + else + { + TSize twips = {0,0}; + SafePut(aSize, &twips, sizeof(twips)); + } + } + return r; + } +/** +Get all the pixel formats available and insert them to a descriptor +@return KErrNone if successful, otherwise a system wide error code. +*/ +TInt DDisplayChannel::GetPixelFormats() + { + TInt r; + __ASSERT_DEBUG(iMsg->Ptr0(), Panic(EDisplayPanicNullArgument)); + __ASSERT_DEBUG(iMsg->Ptr1(), Panic(EDisplayPanicNullArgument)); + //get the number of resolutions (as above) + TPtr8 pixelFormatDes(NULL,0); + TInt length = ((TInt)sizeof(RDisplayChannel::TPixelFormat)) * iPixelFormatArraySize; + pixelFormatDes.Set((TUint8*)iPixelFormatArray, length, length); + r = Kern::ThreadDesWrite(iMsg->Client(),(TDes8*)iMsg->Ptr0(), pixelFormatDes, 0, iMsg->Client()); + if (r == KErrNone) + { + Kern::KUDesSetLength(*(TDes8*)iMsg->Ptr0(), length); + SafePut(iMsg->Ptr1(), &iPixelFormatArraySize, sizeof(iPixelFormatArraySize)); + } + return r; + } + + +TInt DDisplayChannel::SetBufferFormat(RDisplayChannel::TBufferFormat* aBufferFormat) + { + if (!aBufferFormat) + { + ClientPanic(RDisplayChannel::ENullArgument); + return KErrArgument; + } + + if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, + __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)"))) + { + return KErrPermissionDenied; + } + + RDisplayChannel::TBufferFormat bufferFormat; + kumemget32(&bufferFormat, aBufferFormat, sizeof(RDisplayChannel::TBufferFormat)); + + // Validate Size + if (iCurrentResolution.iHeight > bufferFormat.iSize.iHeight || + iCurrentResolution.iWidth > bufferFormat.iSize.iWidth || + bufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth || + bufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth) + { + //return error on failure + return KErrArgument; + } + + // check we received one of the supported formats. + for (TInt i = 0; i < iPixelFormatArraySize; i++) + { + if (bufferFormat.iPixelFormat == iPixelFormatArray[i]) + { + // the arguments are all validated at this point, update the current format + iCurrentBufferFormat = bufferFormat; + return KErrNone; + } + } + + //return error on failure + return KErrArgument; + } + +TInt DDisplayChannel::ValidateBufferFormat(const RDisplayChannel::TBufferFormat& aBufferFormat, + const RDisplayChannel::TResolution& aResolution) + { + // Validate the size reported in buffer format against the given resolution + if (aResolution.iPixelSize.iHeight > aBufferFormat.iSize.iHeight || + aResolution.iPixelSize.iWidth > aBufferFormat.iSize.iWidth || + aBufferFormat.iSize.iHeight > KMaxBufferSizeHeightAndWidth || + aBufferFormat.iSize.iWidth > KMaxBufferSizeHeightAndWidth) + { + //return error on failure + return KErrArgument; + } + + // check we received one of the supported formats. + for (TInt i = 0; i < iPixelFormatArraySize; i++) + { + if (aBufferFormat.iPixelFormat == iPixelFormatArray[i]) + { + return KErrNone; + } + } + + return KErrArgument; + } + +TInt DDisplayChannel::NextPlaneOffset(RDisplayChannel::TBufferFormat* aBufferFormat, + RDisplayChannel::TBufferFormatContext* aContext) + { + if (!aBufferFormat) + { + ClientPanic(RDisplayChannel::ENullArgument); + return KErrArgument; + } + + if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, + __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)"))) + { + return KErrPermissionDenied; + } + + RDisplayChannel::TBufferFormat bufferFormat; + kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat)); + + RDisplayChannel::TResolution resolution; + RDisplayChannel::TDisplayRotation rotation; + + if (aContext) + { + RDisplayChannel::TBufferFormatContext context; + kumemget32(&context, aContext, sizeof(context)); + resolution = context.iResolution; + rotation = context.iRotation; + } + else + { + resolution.iPixelSize = iCurrentResolution; + rotation = iCurrentRotation; + } + + TInt err = ValidateBufferFormat(bufferFormat, resolution); + + if (err != KErrNone) + { + return err; + } + //it assumes no planar pixel formats are supported by this driver implementation + return 0; + } + +TInt DDisplayChannel::NextLineOffset(RDisplayChannel::TBufferFormat* aBufferFormat, + RDisplayChannel::TBufferFormatContext* aContext) + { + if (!aBufferFormat) + { + ClientPanic(RDisplayChannel::ENullArgument); + return KErrArgument; + } + + if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData, + __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY0.LDD (display channel driver)"))) + { + return KErrPermissionDenied; + } + + RDisplayChannel::TBufferFormat bufferFormat; + kumemget32(&bufferFormat, aBufferFormat, sizeof(bufferFormat)); + + RDisplayChannel::TResolution resolution; + RDisplayChannel::TDisplayRotation rotation; + + if (aContext) + { + RDisplayChannel::TBufferFormatContext context; + kumemget32(&context, aContext, sizeof(context)); + resolution = context.iResolution; + rotation = context.iRotation; + } + else + { + resolution.iPixelSize = iCurrentResolution; + rotation = iCurrentRotation; + } + + TInt err = ValidateBufferFormat(bufferFormat, resolution); + + if (err != KErrNone) + { + return err; + } + + TInt bpp = 0; + //validating the pixel format and getting the pixel size in bits + switch (bufferFormat.iPixelFormat) + { + case EUidPixelFormatXRGB_4444: // RGB4444 + case EUidPixelFormatARGB_4444: + case EUidPixelFormatRGB_565: // RGB565 + bpp = 16; + break; + case EUidPixelFormatXRGB_8888: // Really 32bpp, but top 8 unused + case EUidPixelFormatARGB_8888: + case EUidPixelFormatARGB_8888_PRE: + bpp = 32; + break; + default: + // We got an error, it seems. The pixel format is not supported + // Let's panic because the pixel format has just been validated + Panic(EDisplayPanicInvalidBitDepth); + break; + } + + TInt widthInPixel = 0; // pixels + + // let's take in consideration the given rotation + switch (rotation) + { + case RDisplayChannel::ERotation90CW: + case RDisplayChannel::ERotation270CW: + widthInPixel = bufferFormat.iSize.iHeight; + break; + default: // Normal + widthInPixel = bufferFormat.iSize.iWidth; + break; + } + + // we have to round up to 32 bits word. This is a Ms Windows limitation + TInt stride = _ALIGN_UP((widthInPixel * bpp), 32) >> 3; + return stride; + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/display_dev.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/display_dev.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,79 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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 "display_dev.h" +#include "display_chan.h" + + +DECLARE_STANDARD_LDD() + { + return new DDisplayDevice; + } + + +DDisplayDevice::DDisplayDevice() + { + iVersion = TVersion(KDisplayChMajorVersionNumber, + KDisplayChMinorVersionNumber, KDisplayChBuildVersionNumber); + iParseMask=KDeviceAllowUnit; + } + + +DDisplayDevice::~DDisplayDevice() + { + } + + +TInt DDisplayDevice::Install() + { + return SetName(&RDisplayChannel::Name()); + } + + +/** +Called by the kernel's device driver framework to create a Logical Channel. +This is called in the context of the user thread (client) which requested the +creation of a Logical Channel (e.g. through a call to RBusLogicalChannel::DoCreate) +The thread is in a critical section. + +@param aChannel Set to point to the created Logical Channel + +@return KErrNone if successful, otherwise one of the other system wide error codes. +*/ +TInt DDisplayDevice::Create(DLogicalChannelBase*& aChannel) + { + aChannel = new DDisplayChannel(); + + return aChannel ? KErrNone : KErrNoMemory; + } + + +/** +Return the drivers capabilities. +Called in the response to an RDevice::GetCaps() request. + +@param aDes User-side descriptor to write capabilities information into +*/ +void DDisplayDevice::GetCaps(TDes8& aDes) const + { + // Create a capabilities object + DDisplayChannel::TCaps caps; + caps.iVersion = iVersion; + // Write it back to user memory + Kern::InfoCopy(aDes,reinterpret_cast(&caps),sizeof(caps)); + } + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/econsnogui.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/econsnogui.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,115 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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 +#include + +class CNoGuiConsole : public CConsoleBase + { +public: + CNoGuiConsole(); + virtual ~CNoGuiConsole(); + virtual TInt Create(const TDesC &aTitle,TSize aSize); + virtual void Read(TRequestStatus &aStatus); + virtual void ReadCancel(); + virtual void Write(const TDesC &aDes); + virtual TPoint CursorPos() const; + virtual void SetCursorPosAbs(const TPoint &aPoint); + virtual void SetCursorPosRel(const TPoint &aPoint); + virtual void SetCursorHeight(TInt aPercentage); + virtual void SetTitle(const TDesC &aTitle); + virtual void ClearScreen(); + virtual void ClearToEndOfLine(); + virtual TSize ScreenSize() const; + virtual TKeyCode KeyCode() const; + virtual TUint KeyModifiers() const; + }; + +CNoGuiConsole::CNoGuiConsole() + { + } + +CNoGuiConsole::~CNoGuiConsole() + { + } + +TInt CNoGuiConsole::Create(const TDesC& /*aTitle*/, TSize /*aSize*/) + { + return(KErrNone); + } + +void CNoGuiConsole::Read(TRequestStatus &aStatus) + { + TRequestStatus *pS=(&aStatus); + User::RequestComplete(pS, KErrNotSupported); + } + +void CNoGuiConsole::ReadCancel() + { + } + +void CNoGuiConsole::Write(const TDesC& /*aDes*/) + { + } + +TPoint CNoGuiConsole::CursorPos() const + { + return TPoint(0,0); + } + +void CNoGuiConsole::SetCursorPosAbs(const TPoint& /*aPoint*/) + { + } + +void CNoGuiConsole::SetCursorPosRel(const TPoint& /*aPoint*/) + { + } + +void CNoGuiConsole::SetCursorHeight(TInt /*aPercentage*/) + { + } + +void CNoGuiConsole::SetTitle(const TDesC& /*aTitle*/) + { + } + +void CNoGuiConsole::ClearScreen() + { + } + +void CNoGuiConsole::ClearToEndOfLine() + { + } + +TSize CNoGuiConsole::ScreenSize() const + { + return TSize(10,10); + } + +TKeyCode CNoGuiConsole::KeyCode() const + { + return EKeyNull; + } + +TUint CNoGuiConsole::KeyModifiers() const + { + return 0; + } + +extern "C" EXPORT_C TAny *NewConsole() + { + return(new CNoGuiConsole); + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/epoc32.ico Binary file emulator/emulatorbsp/specific/epoc32.ico has changed diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/ethernet.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/ethernet.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,996 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\ethernet.cpp +// PDD for the Ethernet under the windows emulator +// +// + +/** + @file wins/specific/ethernet.cpp +*/ + + +#include +#include "nk_priv.h" +#include "nk_plat.h" +#include + +#include "pcap.h" + + +/** @addtogroup enet Ethernet Drivers + * Kernel Ethernet Support + */ + +/** @addtogroup enet_pdd Driver PDD's + * @ingroup enet + */ + +/** @addtogroup enet_byplatform Ethernet support by platform + * @ingroup enet + */ + +/** @addtogroup enet_wins WINS (Emulator) Ethernet support + * @ingroup enet_byplatform + */ + + +// strings potentially written to ethernet.ini by netcards.exe +#define KEpocIniEthSpeed10Mbps "10Mbps" +#define KEpocIniEthSpeed100Mbps "100Mbps" + +// entries in epoc.ini file: +#define KEpocIniEthSpeedEntry "ETHER_SPEED" +#define KEpocIniEthNIFEntry "ETHER_NIF" +#define KEpocIniEthMACEntry "ETHER_MAC" + +#define KEthDrvPanicCategory "D32ETHER" + +#define KLocalDriverNameMax 256 + +#define PCAP_FILTER "ether dst %x:%x:%x:%x:%x:%x or ether multicast and ether src not %x:%x:%x:%x:%x:%x" + +_LIT(KPddName, "Ethernet.Wins"); + +// needs ldd version.. +const TInt KMinimumLddMajorVersion=1; +const TInt KMinimumLddMinorVersion=0; +const TInt KMinimumLddBuild=122; + +/** @addtogroup enet_windows Windows Emulator Ethernet Pdd + * @ingroup enet_pdd + * @ingroup enet_wins + * @{ + */ + +/** + * The Windows specific Ethernet physical device (factory) class + * @internalTechnology belongs to PDD which sits internally in kernel + */ +class DDriverEthernet : public DPhysicalDevice + { +public: + + /** + * The constructor + * Sets the drivers version number. Limits possible + * number of units to one only (unit 0) + */ + DDriverEthernet(); + + /** + * Inherited from DPhysicalDevice. + * Install the driver by setting it's name + * @return KErrNone on success, other error code on failure + */ + virtual TInt Install(); + + /** + * Inherited from DPhysicalDevice. + * Get the Capabilites of the driver + * NOT supported but required as implementation of + * pure virtual in base class + */ + virtual void GetCaps(TDes8 &aDes) const; + + /** + * Inherited from DPhysicalDevice. + * Create a channel to a device + * @param aChannel a reference to a newly created channel object + * @param aUnit a unit for which the channel is being created + * @param anInfo pointer to a descriptor with additional info (may be NULL) + * @param aVer a requested version + * @return KErrNone on success, other error code on failure + */ + virtual TInt Create(DBase*& aChannel, TInt aUnit, + const TDesC8* anInfo, const TVersion &aVer); + + /** + * Inherited from DPhysicalDevice. + * Validate that the info supplied would create a valid channel + * @param aUnit a unit for which validation is to be done + * @param anInfo pointer to a descriptor with additional info (may be NULL) + * @param aVer a version to be validated + * @return KErrNone if valid, KErrNotSupported otherwise + */ + virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); + }; + + +/** + * The WINS specific Ethernet channel class for the libpcap library + * @internalTechnology belongs to PDD which sits internally in kernel + */ +class DEthernetWins : public DEthernet + { + + /** + * The Worker Thread + * @param aDEthernetWins Pointer to this object + * @return Should never return + */ + friend TInt WorkThread(DEthernetWins * aDEthernetWins); + +public: + + enum TWinsEtherPanic + { + EBadMacAddress = 1, // means bad MAC address in ini file or entry for it missing or ini file missing + ENoNetInterface, // means entry for network interface name missing in ini file or ini file missing + EPcapNull // means Wpcap couldn't be initialised - potentially not installed or name of network interface in ini file wrong + }; + + /** + * The Constructor. + */ + DEthernetWins(); + + /** + * The Destructor. + */ + ~DEthernetWins(); + + /** + * The Isr plays a role of the pcap callback. + * Do NOT call the function directly + * @param thisObject a pointer to this object + * @param header the received packet's pcap header + * @param pkt_data the received packet + * @post new packet is copied to LDD's RX buffers' queue + */ + static void Isr(u_char *thisObject, + const struct pcap_pkthdr *header, + const u_char *pkt_data); + + /** + * The DoCreate Method. + * Sets up the channel as part of the object creation + * and retrieves the MAC address from epoc.ini file. + * Also creates wpcap handler and thread for wpcap loop. + * @pre epoc32\\data\\epoc.ini must exist with entries: "ETHER-NIF=..", "ETHER-MAC=..", "ETHER-SPEED=.." + * @param aUnit a unit for which the channel is being created + * @panic D32ETHER reason: (1) can't get proper MAC address (2) can't get + * network interface name (3) can't initialise wpcap + * @return KErrNone on success, other error code on failure + */ + TInt DoCreate(TInt aUnit); + + /** + * DEthernet implementation. + * Start the receiver. + * Resumes pcap thread. Sets status to ready. + * @return KErrNone on success or suitable error code on failure + */ + virtual TInt Start(); + + /** + * DEthernet implementation. + * Stop the receiver. + * @param aMode possible values are: EStopNormal (=0), EStopEmergency (=1) + * @post pcap thread suspended, status set to not ready + */ + virtual void Stop(TStopMode aMode); + + /** + * DEthernet implementation. + * Validates a new configuration - should be called before Configure() + * @param aConfig is the configuration to be validated + * @return KErrNone if aConfig valid, KErrNotSupported otherwise + * @see Configure() + */ + virtual TInt ValidateConfig(const TEthernetConfigV01 &aConfig) const; + + /** + * DEthernet implementation. + * Configure the PDD and pcap library + * Reconfigure the library using the new configuration supplied. + * Sets pcap filter to read only frames with destination address set to + * broadcast, multicast or MAC addresss from defaultConfig. + * This will not change the MAC address. + * @param aConfig The new configuration + * @return KErrNone on success, suitable error code otherwise + * @see ValidateConfig() + * @see MacConfigure() + */ + virtual TInt Configure(TEthernetConfigV01 &aConfig); + + /** + * DEthernet implementation. + * Change the MAC address - writes new MAC address in defaultConfig. + * If new settings are to have any effect then pcap filter + * ought to be set again which is done by 'Configure()' + * @param aConfig a configuration structure containing the new MAC + * @see Configure() + */ + virtual void MacConfigure(TEthernetConfigV01 &aConfig); + + /** + * DEthernet implementation. + * Get the current config from defaultConfig member varaiable + * which is assumed to be up to date. + * Fills in the following fields: + * The Transmit Speed + * The Duplex Setting + * The MAC address + * @param aConfig is a TEthernetConfigV01 reference that will be filled in + */ + virtual void GetConfig(TEthernetConfigV01 &aConfig) const; + + /** + * DEthernet implementation. + * Dummy method, required as pure virtual in base class + */ + virtual void CheckConfig(TEthernetConfigV01 &aConfig); + + /** + * DEthernet implementation. + * Should query the capabilites. + * NOT supported but required as pure virtual in base class + */ + virtual void Caps(TDes8 &aCaps) const; + + /** + * DEthernet implementation. + * Transmit data via wpcap + * @param aBuffer reference to the data to be sent + * @return KErrNone on success, other error code on failure + */ + virtual TInt Send(TBuf8 &aBuffer); + + /** + * DEthernet implementation. + * Retrieve data + * Pull the received data out of the pcap library and into the supplied buffer. + * Need to be told if the buffer is OK + * @param aBuffer Reference to the buffer to be used to store the data in + * @param okToUse Bool to indicate if the buffer is usable + * @return KErrNone on success, other error code on failure + */ + virtual TInt ReceiveFrame(TBuf8 &aBuffer, TBool okToUse); + + /** + * DEthernet implementation. + * Disables all IRQ's + * @return The IRQ level before it was changed + * @see RestoreIrqs() + */ + virtual TInt DisableIrqs(); + + /** + * DEthernet implementation. + * Restore the IRQ's to the supplied level + * @param aIrq The level to set the irqs to. + * @see DisableIrqs() + */ + virtual void RestoreIrqs(TInt aIrq); + + /** + * DEthernet implementation. + * Return the DFC Queue that this device should use + * @param aUnit a channel's unit number (ignored - only one unit possible) + * @return a DFC Queue to use + */ + virtual TDfcQue* DfcQ(TInt aUnit); + + +private: + static TBool DEthernetWins::IsTcp(TDesC8 &aFrame); + static TInt DEthernetWins::GetTcpAckNumber(TDesC8 &frame); + static TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &frame); + /** + * Read network interface to be used from configuration file. Panic if + * pre-conditions are not satisfied. + * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-NIF=existing_nif_name" + * @post network interface name put in a member variable: iNetInterfaceName + * @panic D32ETHER reason: (2) can't get network interface name + */ + void SetDriverName(); + + /** + * Read MAC address from a configuration file and put it + * into defaultConfig member variable checking before if the + * one from the file is correct. Panic if pre-conditions are not satisfied + * (although in case when MAC address is improper). + * @pre epoc32\\data\\epoc.ini must exist with entry: "ETHER-MAC=proper_mac_address" + * @panic D32ETHER reason: EBadMacAddress + * @return KErrNone on success (panics on failure) + */ + TInt SetMacAddress(); + + +private: + + /** + * The handle to the pcap interface - wpcap specific + */ + pcap_t * iPcapPtr; + + /** + * Saved received packet information - wpcap specific: + * pointer to a structure that holds general information about the packet: + * the time in which it was sniffed, the length of this packet, + * and the length of his specific portion (in case it is fragmented) + */ + const struct pcap_pkthdr * iPcapHeader; + + /** + * Saved receive packet data - wpcap specific + */ + const u_char * iPcapPktData; + + /** + * Id of the receiver - wpcap thread + */ + unsigned long iWorkerThreadId; + + /** + * Contains the handle to wpcap thread. + */ + HANDLE iThreadHandle; + + /** + * Stores the unit number (only one interface possible in + * this implementation, so it will have value "0") + */ + TInt iUnit; + + /** + * Is ETrue if the chip has been fully configured and is ready + * for receiving frames. Is set to ETrue in Start(), to EFalse + * in Stop(). Initialized in constructor as EFalse. + */ + TBool iReady; + + /** + * Contains the default/current configuration of the driver. + * Updated whenever configuration is to be changed. + */ + TEthernetConfigV01 defaultConfig; + + /** + * Contains the network interface name to be used + * @see SetDriverName() + */ + char iNetInterfaceName[KLocalDriverNameMax]; + + }; + +/** @} */ // End of wins ethernet pdd + + + +DDriverEthernet::DDriverEthernet() +// Constructor + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::DDriverEthernet()")); + iUnitsMask=0x1; // support unit 0 only + iVersion=TVersion(KEthernetMajorVersionNumber, + KEthernetMinorVersionNumber, + KEthernetBuildVersionNumber); + + } + + +TInt DDriverEthernet::Install() +// Install the driver + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Install()")); + return SetName(&KPddName); + } + + +void GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit=0) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("GetWinsEthernetsCaps(TDes8 &aCaps, TInt aUnit)")); + TEthernetCaps capsBuf; + + aUnit=0; + + aCaps.FillZ(aCaps.MaxLength()); + aCaps=capsBuf.Left(Min(capsBuf.Length(),aCaps.MaxLength())); + } + +void PanicFromWinsEtherDrv(TInt aReason) + { + Kern::Fault(KEthDrvPanicCategory, aReason); + } + +void DDriverEthernet::GetCaps(TDes8 &aDes) const +// Return the driver's capabilities + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::GetCaps(TDes8 &aDes) const")); + GetWinsEthernetsCaps(aDes); + } + + +TInt DDriverEthernet::Create(DBase*& aChannel, + TInt aUnit, + const TDesC8* aInfo, + const TVersion& aVer) +// Create a driver + { + __KTRACE_OPT(KHARDWARE, + Kern::Printf("DDriverEthernet::Create(DBase*& aChannel, TInt aUnit, const TDesC8* nInfo, const TVersion& aVer)")); + + TInt ret; + + ret = Validate( aUnit, aInfo, aVer); + if ( KErrNone != ret ) + return ret; + + ret = KErrNoMemory; + + DEthernetWins* ptrPdd = new DEthernetWins; + + + if ( ptrPdd ) + { + ret = ptrPdd->DoCreate(aUnit); + if ( ret != KErrNone) + { + delete ptrPdd; + } + else + aChannel = ptrPdd; + } + + + return ret; + } + + +TInt DDriverEthernet::Validate(TInt aUnit, + const TDesC8* /*aInfo*/, + const TVersion& aVer) +// Validate the requested configuration + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DDriverEthernet::Validate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)")); + if ((!Kern::QueryVersionSupported(iVersion,aVer)) || + (!Kern::QueryVersionSupported(aVer,TVersion(KMinimumLddMajorVersion, + KMinimumLddMinorVersion, + KMinimumLddBuild)))) + { + return KErrNotSupported; + } + + if (aUnit != 0) + { + return KErrNotSupported; + } + + return KErrNone; + } + + +DEthernetWins::DEthernetWins() +// Constructor + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DEthernetWins()")); + + iReady = EFalse; + + // set default configuration - must be set before DoCreate gets called + defaultConfig.iEthSpeed = KEthSpeedUnknown; + defaultConfig.iEthDuplex = KEthDuplexUnknown; + + // MAC address initially set to NULL + defaultConfig.iEthAddress[0] = 0; + defaultConfig.iEthAddress[1] = 0; + defaultConfig.iEthAddress[2] = 0; + defaultConfig.iEthAddress[3] = 0; + defaultConfig.iEthAddress[4] = 0; + defaultConfig.iEthAddress[5] = 0; + + iNetInterfaceName[0] = '\0'; + + // wpcap + iPcapPtr = NULL; + + } + +DEthernetWins::~DEthernetWins() +// Destructor + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::~DEthernetWins()")); + + if (iPcapPtr) + { + pcap_close(iPcapPtr); + iPcapPtr = NULL; + } + + } + + +TInt DEthernetWins::DoCreate(TInt aUnit)//, const TDesC8* /*anInfo*/) +// Sets up the PDD + { + __KTRACE_OPT(KHARDWARE, + Kern::Printf("DEthernetWins::DoCreate(TInt aUnit, const TDesC8* /*anInfo*/)")); + + iUnit = aUnit; + + TInt ret = KErrNone; + + SetMacAddress(); // will panic if can't get proper MAC address + + const char* speedProperty = Property::GetString(KEpocIniEthSpeedEntry); + + if( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed10Mbps )) ) + { + defaultConfig.iEthSpeed = KEthSpeed10BaseT; + } + else if ( (NULL==speedProperty) ? 0 : (0 == strcmp( speedProperty, KEpocIniEthSpeed100Mbps )) ) + { + defaultConfig.iEthSpeed = KEthSpeed100BaseTX; + } + + SetDriverName(); + + char errPcap[PCAP_ERRBUF_SIZE]; + + if( iPcapPtr == NULL ) + { + + if((iPcapPtr = pcap_open_live( iNetInterfaceName, + 2000, + 1, + 20, + errPcap)) != NULL) + { + + if ((iThreadHandle = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)WorkThread, + this, + CREATE_SUSPENDED, + &iWorkerThreadId)) != NULL) + { + ret = Configure(defaultConfig); + } + else + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("CreateThread() failed to create worker thread")); + ret = KErrBadHandle; + } + } + else + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_open_live() failed to open")); + //ret = KErrCouldNotConnect; + PanicFromWinsEtherDrv( EPcapNull ); + } + + } + + if(ret != KErrNone) + { + // Failed to init all so tidy up + if( iPcapPtr ) + { + pcap_close(iPcapPtr); + iPcapPtr = NULL; + } + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate() returned with ERROR")); + return ret; + } + + + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DoCreate %2x:%2x:%2x:%2x:%2x:%2x", + defaultConfig.iEthAddress[0], + defaultConfig.iEthAddress[1], + defaultConfig.iEthAddress[2], + defaultConfig.iEthAddress[3], + defaultConfig.iEthAddress[4], + defaultConfig.iEthAddress[5])); + + return ret; + } + + +void DEthernetWins::SetDriverName() + { + __KTRACE_OPT(KHARDWARE, + Kern::Printf("DEthernetWins::SetDriverName()")); + + const char* property = Property::GetString(KEpocIniEthNIFEntry); + + __ASSERT_ALWAYS( (NULL != property), + PanicFromWinsEtherDrv(ENoNetInterface) ); + + memcpy( iNetInterfaceName, property, strlen(property) ); + } + + +TInt DEthernetWins::SetMacAddress() +// reads MAC address from epoc.ini file and writes into defaultConfig + { + + __KTRACE_OPT(KHARDWARE, + Kern::Printf("DEthernetWins::SetMacAddress()")); + + TUint8 tempAddress[6]; + + const char *tempBuffer = Property::GetString(KEpocIniEthMACEntry); + + __ASSERT_ALWAYS( ((tempBuffer != NULL) && (strlen(tempBuffer) >= 6)), + PanicFromWinsEtherDrv(EBadMacAddress) ); + + + TBuf<20> validCharsLower(_L("0123456789abcdef")); + TBuf<20> validCharsUpper(_L("0123456789ABCDEF")); + TUint8 value; + TUint8 upper=0; + TChar c; + TInt pos; + TInt i; + for( i=0; i<6; i++) + { + c = tempBuffer[2*i]; + if(((pos = validCharsLower.Locate(c)) == KErrNotFound) && + ((pos = validCharsUpper.Locate(c)) == KErrNotFound)) + { + PanicFromWinsEtherDrv( EBadMacAddress ); + } + upper = (TUint8)pos; + c = tempBuffer[(2*i)+1]; + if( ((pos = validCharsLower.Locate(c)) == KErrNotFound) && + ((pos = validCharsUpper.Locate(c)) == KErrNotFound) ) + { + PanicFromWinsEtherDrv( EBadMacAddress ); + } + + value = (TUint8)pos; + value = (TUint8)((upper<<4) | value); + tempAddress[i] = value; + } + + for( i=0; i<6; i++ ) + { + defaultConfig.iEthAddress[i] = tempAddress[i]; + } + + return KErrNone; + + } + + +TDfcQue* DEthernetWins::DfcQ(TInt /*aUnit*/) +// Return the DFC queue to be used for this device + { + __KTRACE_OPT(KHARDWARE, + Kern::Printf("DEthernetWins::DfcQ(TInt )")); + return Kern::DfcQue0(); + } + + +TInt DEthernetWins::Start() +// Start receiving frames + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Start()")); + + TInt32 ret; + + // Start thread + // ResumeThread() - from MSDN help: + // This function decrements a thread’s suspend count. + // When the suspend count is decremented to zero, + // the execution of the thread is resumed. + // Return value: The thread’s previous suspend count indicates success. 0xFFFFFFFF indicates failure + ret = ResumeThread( iThreadHandle ); + if( (0xFFFFFFFF == ret) )//|| (ret > 1) ) + return KErrGeneral; + + iReady = ETrue; + + return KErrNone; + } + + +void DEthernetWins::Stop(TStopMode aMode) +// Stop receiving frames + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Stop(TStopMode aMode)")); + + + switch (aMode) + { + case EStopNormal: + case EStopEmergency: + SuspendThread(iThreadHandle); + iReady = EFalse; + break; + default: + SuspendThread(iThreadHandle); + iReady = EFalse; + break; + } + + } + + +TInt DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const +// Validate a config structure. + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ValidateConfig(const TEthernetConfigV01 &aConfig) const")); + switch(aConfig.iEthSpeed) + { + case KEthSpeedUnknown: + case KEthSpeedAuto: + case KEthSpeed10BaseT: + case KEthSpeed100BaseTX: + break; + default: + return KErrNotSupported; + } + + switch(aConfig.iEthDuplex) + { + case KEthDuplexUnknown: + case KEthDuplexAuto: + case KEthDuplexHalf: + case KEthDuplexFull: + break; + default: + return KErrNotSupported; + } + + return KErrNone; + } + + +void DEthernetWins::CheckConfig(TEthernetConfigV01& /*aConfig*/) +// dummy implementation of pure virtual function + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::CheckConfig(TEthernetConfigV01& aConfig)")); + } + +TInt DEthernetWins::Send(TBuf8 &aBuffer) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send(TBuf8 &aBuffer)")); + TUint16 * dataP = (TUint16 *)aBuffer.Ptr(); + TUint16 length = TUint16(aBuffer.Length()); + + TInt ret; + + if (iPcapPtr) + { + __KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf(" >pdd tx: sending tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) )); + if(pcap_sendpacket(iPcapPtr, (unsigned char *)dataP, length)) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send - pcap_sendpacket() failed ")); + + ret = KErrWrite; + } + else + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send: \n*** completed pcap_sendpacket() ***\n")); + ret = KErrNone; + } + } + else + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Send() pcap adapter NOT open\n")); + ret = KErrNotReady; + } + + return ret; + } + + +TInt DEthernetWins::DisableIrqs() +// Disable normal interrupts + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::DisableIrqs()")); + return NKern::DisableInterrupts(1); + } + + +void DEthernetWins::RestoreIrqs(TInt aLevel) +// Restore normal interrupts + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::RestoreIrqs(TInt aLevel)")); + NKern::RestoreInterrupts(aLevel); + } + + +void DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::MacConfigure(TEthernetConfigV01 &aConfig)")); + defaultConfig.iEthAddress[0] = aConfig.iEthAddress[0]; + defaultConfig.iEthAddress[1] = aConfig.iEthAddress[1]; + defaultConfig.iEthAddress[2] = aConfig.iEthAddress[2]; + defaultConfig.iEthAddress[3] = aConfig.iEthAddress[3]; + defaultConfig.iEthAddress[4] = aConfig.iEthAddress[4]; + defaultConfig.iEthAddress[5] = aConfig.iEthAddress[5]; + } + + +TInt DEthernetWins::Configure(TEthernetConfigV01 & /*aConfig*/) +// Set a wpcap filter + { + + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Configure(TEthernetConfigV01 &aConfig)")); + + char errPcap[PCAP_ERRBUF_SIZE]; + TInt ret = KErrNone; + char filter[128]; + struct bpf_program fcode; + bpf_u_int32 SubNet,NetMask; + + //obtain the subnet + pcap_lookupnet( iNetInterfaceName, &SubNet, &NetMask, errPcap); + + sprintf(filter, + PCAP_FILTER, //pcap_filter, + defaultConfig.iEthAddress[0], + defaultConfig.iEthAddress[1], + defaultConfig.iEthAddress[2], + defaultConfig.iEthAddress[3], + defaultConfig.iEthAddress[4], + defaultConfig.iEthAddress[5], + defaultConfig.iEthAddress[0], + defaultConfig.iEthAddress[1], + defaultConfig.iEthAddress[2], + defaultConfig.iEthAddress[3], + defaultConfig.iEthAddress[4], + defaultConfig.iEthAddress[5]); + + + //compile the filter + if( 0 != pcap_compile(iPcapPtr, &fcode, filter, 1, NetMask) ) + { + // failed to compile: + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_compile() failed")); + ret = KErrUnknown; + } + else + { + // compiled successfully: set the filter + if( 0 != pcap_setfilter(iPcapPtr, &fcode)) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("pcap_setfilter() failed")); + ret = KErrUnknown; + } + } + + return ret; + } + + +void DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const +// Get the current config from defaultConfig member + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::GetConfig(TEthernetConfigV01 &aConfig) const")); + aConfig = defaultConfig; + } + + +void DEthernetWins::Caps(TDes8 &aCaps) const +// return PDD's capabilites + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Caps(TDes8 &aCaps) const")); + GetWinsEthernetsCaps(aCaps,iUnit); + } + + +void DEthernetWins::Isr( u_char *thisObject, + const struct pcap_pkthdr *header, + const u_char *pkt_data) +// pcap callback fuction + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::Isr()")); + + DEthernetWins& thisPdd = *(DEthernetWins*) thisObject; + + StartOfInterrupt(); + + thisPdd.iPcapHeader = header; + thisPdd.iPcapPktData = pkt_data; + + thisPdd.ReceiveIsr(); + + EndOfInterrupt(); + + return; + } + + +TInt DEthernetWins::ReceiveFrame(TBuf8 &aBuffer, TBool okToUse) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("DEthernetWins::ReceiveFrame(TBuf8 &aBuffer)")); + + // If no buffer available dump frame + if(!okToUse) + { + return KErrGeneral; + } + + aBuffer.Copy(iPcapPktData, iPcapHeader->len); + aBuffer.SetLength(iPcapHeader->len); + __KTRACE_OPT2(KHARDWARE, KSCRATCH, Kern::Printf(" >pdd rx: tcp seq=%u ack=%u", GetTcpSeqNumber(aBuffer), GetTcpAckNumber(aBuffer) )); + + return KErrNone; + } + +#ifdef _DEBUG +const TUint8 ETHER2_TYPE_IP_MSB = 0x08; +const TUint8 ETHER2_TYPE_IP_LSB = 0x00; +const TUint8 IP_TYPE_TCP = 0x06; + +TBool DEthernetWins::IsTcp(TDesC8 &aFrame) + { + return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP); + } + +TInt DEthernetWins::GetTcpSeqNumber(TDesC8 &aFrame) + { + TInt seqNum = 0; + if (IsTcp(aFrame)) + seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41]; + return seqNum; + } + +TInt DEthernetWins::GetTcpAckNumber(TDesC8 &aFrame) + { + TInt ackNum = 0; + if (IsTcp(aFrame)) + ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45]; + return ackNum; + } +#endif + +TInt WorkThread(DEthernetWins * aDEthernetWins) + { + __KTRACE_OPT(KHARDWARE, Kern::Printf("WorkThread(DEthernetWins * aDEthernetWins)")); + + return pcap_loop(aDEthernetWins->iPcapPtr, 0, DEthernetWins::Isr, (unsigned char *)aDEthernetWins); + } + +/** + * @addtogroup enet_windows + * @{ + */ + +/** + * Real entry point from the Kernel: return a new driver + * (Macro wrapping: EXPORT_C DPhysicalDevice *CreatePhysicalDevice() ) + */ +DECLARE_STANDARD_PDD() + { + return new DDriverEthernet; + } + + +/** @} */ // end of windows group diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/gui.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/gui.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,4920 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\gui.cpp +// +// +#define WINVER 0x0500 + +#include "gui.h" +#include +#include +#include +#include +#include "variant.h" +#include "resource.h" +#include "winsgui.h" +#include "display_chan.h" +#include "pixelformats.h" +#include "multitouch.h" + +#include "monitors.h" + +//Define these so that emulator generates varying values for gce stride and offset. +//By default in emulator, stride is exactly right for display resolution and offset is zero +//Setting these will identify code which incorrectly calculates these factors instead of requesting them +//Note that multiples of 4 bytes are preferred for various reasons. +//[3/5/07 The Secure presentation burffer ignores stride extra because it uses a windows bitmap header to render.] +// #define TEST_GCE_VARIABLE_STRIDE_EXTRA 16 //This constant is added to each mode's scanline length in bytes. It may cause a break if enabled because the iDisplayBufferOffset is not being set +// #define TEST_GCE_VARIABLE_START_EXTRA 16 //A multiple of this is added to each mode's start address in bytes +// #define ASSYMETRIC_SQUARE_STRIDE //If this is defined and the width==height the the stride will not be the same! + +enum + { + KMaskModeNum=0x0FFFFFFF, + KMaskModeFlag8=0x80000000, + KMaskModeFlag4=0x40000000, + KMaskModeFlag2=0x20000000, + KMaskModeFlag1=0x10000000, + + KModeFlagFlipped=KMaskModeFlag8, + + }; +enum + { + KMaskScreenNum=0x0FFF, + KMaskScreenFlag8=0x8000, + KMaskScreenFlag4=0x4000, + KMaskScreenFlag2=0x2000, + KMaskScreenFlag1=0x1000, + + KScreenFlagSecure=KMaskScreenFlag8, + + }; +const TInt KMaxDisplayColors=16777216; +const TInt KMaxDisplayContrast=1; + +static TEmulatorFlip* CurrentFlipState=NULL; +static TInt CurrentConfiguration = 0; +static TInt SavedFlipMessage = 0; + +DWinsUi *systemIni=NULL; +DMasterIni* masterIni; + +DMultiTouch* TheMultiTouch; +static HWND TheControlWin; +static HWND* TheChildWin=NULL; +static HWND* TheWin=NULL; +static HWND hwndStatus; // To display the X,Y,Z information of each mouse +static TInt VirtualKeyPressed = EStdKeyNull; +static HBITMAP* TheScreenBitmap=NULL; +static TUint LedMask; +static TBool WsSwitchOnScreen; + +const char * DefaultWindowTitle = "Symbian OS Emulator"; + +#ifdef __VC32__ + +#ifdef _DEBUG +const char * VersionText = " - wins udeb"; +#else +const char * VersionText = " - wins urel"; +#endif + +#else +#ifdef __CW32__ + +#ifdef _DEBUG +const char * VersionText = " - winscw udeb"; +#else +const char * VersionText = " - winscw urel"; +#endif + +#else +//not winscw or wins! +#ifdef _DEBUG +const char * VersionText = " - unknown udeb"; +#else +const char * VersionText = " - unknown urel"); +#endif + +#endif +#endif + +void Inactive(); +void Active(); +void DrawLeds(); +void UpdateModifiers(); +TInt DisplayHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2); +LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd); + +GLDEF_C const char* skipws(const char* aPtr) + { + while (isspace(*aPtr)) + ++aPtr; + return aPtr; + } + +GLDEF_C const char* skiptok(const char* aPtr) + { + while (isalnum(*aPtr)) + ++aPtr; + return aPtr; + } + +GLDEF_C TInt CompareI(const TDesC8& aLhs, const TDesC8& aRhs) +// +// Case insensitive comparison of descriptors +// (TDesC::CompareF not available to kernel side code) +// + { + TInt ll = aLhs.Length(); + TInt rl = aRhs.Length(); + TInt len = Min(ll, rl); + TInt k = _strnicmp((const char*)aLhs.Ptr(), (const char*)aRhs.Ptr(), len); + return k != 0 ? k : ll - rl; + } + +GLDEF_C TInt MultiProperty(TInt (*aHandler)(TAny* aObj, const char*), TAny* aPtr, const char* aProperty) + { + const char* value = Property::GetString(aProperty); + if (!value) + return KErrNone; + for (;;) + { + TInt r = aHandler(aPtr, value); + if (r != KErrNone) + return r; + const char* ev = strchr(value, ';'); + if (!ev) + break; + value = ev + 1; + } + return KErrNone; + } + +class DWinsGuiPowerHandler : public DPowerHandler + { +public: // from DPowerHandler + void PowerDown(TPowerState); + void PowerUp(); +public: + static DWinsGuiPowerHandler* New(); + void ScreenOn(); + void ScreenOff(); + void ScreenOn(TInt aScreen); + void ScreenOff(TInt aScreen); +public: + DWinsGuiPowerHandler(); + TBool ProcessEvent(const TRawEvent* aEvent); + TBool ProcessEventDfc(const TRawEvent* aEvent); + TBool iStandby; + }; + +static DWinsGuiPowerHandler* WinsGuiPowerHandler; + +_LIT(KWinsGuiName, "WinsGui"); + +DWinsGuiPowerHandler* DWinsGuiPowerHandler::New() + { + DWinsGuiPowerHandler* self = new DWinsGuiPowerHandler(); + if (!self) + return NULL; + self->Add(); + + return self; + } + +DWinsGuiPowerHandler::DWinsGuiPowerHandler() : DPowerHandler(KWinsGuiName) + { + } + +void DWinsGuiPowerHandler::ScreenOff() + { + for(TInt ix=0;ixiScreens.Count();ix++) + ScreenOff(ix); + } + +void DWinsGuiPowerHandler::ScreenOn() + { + for(TInt ix=0;ixiScreens.Count();ix++) + ScreenOn(ix); + } + +void DWinsGuiPowerHandler::ScreenOff(TInt aScreen) + { + PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, FALSE, NULL); + systemIni->iScreens[aScreen]->iScreenOff = ETrue; + } + +void DWinsGuiPowerHandler::ScreenOn(TInt aScreen) + { + PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, TRUE, NULL); + systemIni->iScreens[aScreen]->iScreenOff = EFalse; + } + +void DWinsGuiPowerHandler::PowerDown(TPowerState aState) + { + if (aState == EPwStandby) + iStandby = ETrue; + ScreenOff(); + PowerDownDone(); + } + + +void DWinsGuiPowerHandler::PowerUp() + { + iStandby = EFalse; + ScreenOn(); + PowerUpDone(); + } + +// called in the interrupt context +TBool DWinsGuiPowerHandler::ProcessEvent(const TRawEvent* aEvent) + { + if (!iStandby) + // Pass through + return EFalse; + + if ((aEvent->Type() == TRawEvent::EKeyDown)) + { + Wins::Self() -> AssertWakeupSignal(); + } + + // Ignore + return ETrue; + } + +// called in DFC +TBool DWinsGuiPowerHandler::ProcessEventDfc(const TRawEvent* aEvent) + { + if (aEvent->Type() == TRawEvent::EKeyDown) + { + Wins::Self() -> WakeupEvent(); + if (aEvent->ScanCode() == EStdKeyF5) + { + // Simulate a media change interrupt (media removed) + Wins::MediaChangeCallBack(); + *Wins::MediaDoorOpenPtr()=ETrue; + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF8) + { + TRawEvent v; + v.Set(TRawEvent::ECaseClose); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF8) + { + TRawEvent v; + v.Set(TRawEvent::ECaseClose); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyOff) + { + // Pass through + return EFalse; + } + if (aEvent->ScanCode() == EStdKeyF10) + { + TRawEvent v; + v.Set(TRawEvent::ESwitchOff); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF11) + { + TRawEvent v; + v.Set(TRawEvent::ECaseOpen); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + } + else if (aEvent->Type() == TRawEvent::EKeyUp) + { + if (aEvent->ScanCode() == EStdKeyF10) + // Ignore + return ETrue; + + if (aEvent->ScanCode() == EStdKeyF5) + { + // Simulate a media change interrupt (media Present) + *Wins::MediaDoorOpenPtr()=EFalse; + return ETrue; + } + } + + // Path through + return EFalse; + } + +class EventQ + { + enum {ESize = 16}; +public: + EventQ(); + void Add(const TRawEvent& aEvent); +private: + static void Dfc(TAny* aPtr); + void Empty(); +private: + TDfc iDfc; + TRawEvent* iTail; + TRawEvent iQ[ESize]; + }; + +EventQ::EventQ() + :iDfc(&EventQ::Dfc, this, Kern::DfcQue0(), 6), iTail(iQ) + {} + + +void EventQ::Add(const TRawEvent& aEvent) + { + StartOfInterrupt(); + if (WinsGuiPowerHandler->ProcessEvent(&aEvent)) + { + EndOfInterrupt(); + return; + } + + TRawEvent* pE = iTail; + if (pE != &iQ[ESize]) + { + *pE = aEvent; + iTail = pE + 1; + if (pE == iQ) + iDfc.Add(); + } + EndOfInterrupt(); + } + +void EventQ::Dfc(TAny* aPtr) + { + static_cast(aPtr)->Empty(); + } + +void EventQ::Empty() +// +// Called in the DFC +// + { + TInt irq; + TRawEvent* pE = iQ; + for (;;) + { + if (!WinsGuiPowerHandler->ProcessEventDfc(pE)) + Kern::AddEvent(*pE); + ++pE; + irq = NKern::DisableAllInterrupts(); + if (pE == iTail) + break; + NKern::RestoreInterrupts(irq); + } + iTail = iQ; + NKern::RestoreInterrupts(irq); + } + +LOCAL_D EventQ TheEventQ; + +// Virtual keys + + +VirtualKey::VirtualKey(const TInt aCommandData, const TEmulCommand aCommand) : iCommand(aCommand), iData(aCommandData) + { + } + +TBool VKRect::Contains(TInt aX, TInt aY) const + { + return (aX >= iLeft && aX < iRight && aY >= iTop && aY < iBottom); + } + +VKRect::VKRect(const TInt aCommandData, const TEmulCommand aCommand, TInt aX, TInt aY, TInt aWidth, TInt aHeight) : + VirtualKey(aCommandData, aCommand) + { + iLeft = aX; + iTop = aY; + iRight = aX + aWidth; + iBottom = aY + aHeight; + } + + + +void VKRect::Draw(HDC aHdc,COLORREF aColor) const + { + HPEN pen; + pen=CreatePen(PS_SOLID, 2, aColor); + SelectObject(aHdc, pen); + POINT point; + + MoveToEx(aHdc, (int)iLeft, (int)iTop, &point); + LineTo(aHdc, (int)iLeft, (int)iBottom); + LineTo(aHdc, (int)iRight, (int)iBottom); + LineTo(aHdc, (int)iRight, (int)iTop); + LineTo(aHdc, (int)iLeft, (int)iTop); + } + + +KeyCombination::KeyCombination(const TInt aCommandData, TEmulCommand aCommand): + iData(aCommandData), + iCommand(aCommand) +{ + for (TInt i=0;i=0)//if at least one key is not pressed, we return false + return EFalse; + } + return ETrue; +} + +TBool KeyCombination::AddKey(TStdScanCode aKey) +{ + TInt i; + for (i=0;i iMaxScreenWidth) + iMaxScreenWidth = screenWidth; + wsprintfA(property, "Configuration[%d][%d]ScreenHeight", count, aScreen); + screenHeight = Property::GetInt(property, KScreenHeight); + screenHeight = (screenHeight + 3) & ~3; + if (screenHeight > iMaxScreenHeight) + iMaxScreenHeight = screenHeight; +// + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth", count, aScreen); + physicalScreenWidth = Property::GetInt(property); + if (physicalScreenWidth > iMaxPhysicalScreenWidth) + iMaxPhysicalScreenWidth = physicalScreenWidth; + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight", count, aScreen); + physicalScreenHeight = Property::GetInt(property); + if (physicalScreenHeight > iMaxPhysicalScreenHeight) + iMaxPhysicalScreenHeight = physicalScreenHeight; + } + + // Read figures for current configuration + TInt givenWidth, givenHeight; + wsprintfA(property, "Configuration[%d][%d]ScreenWidth",aConf,aScreen); + givenWidth = Property::GetInt(property, KScreenWidth); + iScreenWidth = (givenWidth + 3) & ~3; + wsprintfA(property, "Configuration[%d][%d]ScreenHeight",aConf,aScreen); + givenHeight = Property::GetInt(property, KScreenHeight); + iScreenHeight = (givenHeight + 3) & ~3; + // Width of screen should be multiple number of 4 pixels. + if (givenWidth & 3 || givenHeight & 3) + { + Kern::Printf("Width and Height of Screen should be multiple number of 4 pixels.\n" + "\tWidth of screen[%d] set to: %d\n\tHeight of screen[%d] set to: %d", + aScreen, iScreenWidth, aScreen, iScreenHeight); + } + +// + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth",aConf,aScreen); + iPhysicalScreenWidth = Property::GetInt(property); + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight",aConf,aScreen); + iPhysicalScreenHeight = Property::GetInt(property); +// + wsprintfA(property, "Configuration[%d][%d]ScreenOffsetX",aConf,aScreen); + iScreenOffsetX = Property::GetInt(property, KScreenOffsetX); + wsprintfA(property, "Configuration[%d][%d]ScreenOffsetY",aConf,aScreen); + iScreenOffsetY = Property::GetInt(property, KScreenOffsetY); + + wsprintfA(property, "Configuration[%d][%d]CompositionBuffers",aConf,aScreen); + iCompositionBuffers = Property::GetInt(property, KCompositionBuffers); + + wsprintfA(property, "Configuration[%d][%d]RefreshRateHz",aConf,aScreen); + iRefreshRateHz = Property::GetInt(property, KRefreshRateHz); + + + wsprintfA(property, "Configuration[%d][%d]ColorDepth",aConf,aScreen); + const char* colors = Property::GetString(property); + if (colors) + { + TUint colorDepth=0; + const char* end = colors; + for (;;) + { + const char* beg = skipws(end); + if(*beg==';') + break; + if (!*beg) + break; + end = skiptok(beg); + if (_strnicmp("Gray2",beg,end-beg) == 0) + { + colorDepth|=KEmulGray2|KEmulIsBitMask; + } + else if (_strnicmp("Gray4",beg,end-beg) == 0) + { + colorDepth|=KEmulGray4|KEmulIsBitMask; + } + else if (_strnicmp("Gray16",beg,end-beg) == 0) + { + colorDepth|=KEmulGray16|KEmulIsBitMask; + } + else if (_strnicmp("Gray256",beg,end-beg) == 0) + { + colorDepth|=KEmulGray256|KEmulIsBitMask; + } + else if (_strnicmp("Color16",beg,end-beg) == 0) + { + colorDepth|=KEmulColor16|KEmulIsBitMask; + } + else if (_strnicmp("Color256",beg,end-beg) == 0) + { + colorDepth|=KEmulColor256|KEmulIsBitMask; + } + else if (_strnicmp("Color4K",beg,end-beg) == 0) + { + colorDepth|=KEmulColor4K|KEmulIsBitMask; + } + else if (_strnicmp("Color64K",beg,end-beg) == 0) + { + colorDepth|=KEmulColor64K|KEmulIsBitMask; + } + else if (_strnicmp("Color16M",beg,end-beg) == 0) + { + colorDepth|=KEmulColor16M|KEmulIsBitMask; + } + else + return KErrArgument; + } + iColorDepth = colorDepth; + + } + //multiple mode support is currently only for GCE. + //I fill this array in before knowing if GCE will be instanced. + if (iColorDepth&KEmulIsBitMask) + { + //iModeDepths is only used by GCE + TInt colorDepth=MaskGceOnly(iColorDepth); + TInt setMode=0; + for (TInt i=1;i!=KEmulIsBitMask;i+=i) + if (colorDepth&i) + iModeDepths[setMode++]=BitsForSingleMode(i); + iMaxModes= setMode; + iModeDepths[setMode++]=0; //a bit width of 0 is illegal + } + else + { + iModeDepths[0]=iColorDepth; + iMaxModes=1; + iModeDepths[1]=0; //a bit width of 0 is illegal + } + + wsprintfA(property, "Configuration[%d][%d]FasciaBitmap",aConf,aScreen); + const char* fascia = Property::GetString(property); + if (fascia) + { + TInt len = strlen(fascia); + //the path may have quotes at the start and end + //need to work out if this is an absolute or relative path + if (fascia[0] == '\"') + { + ++fascia; + --len; + if (--len > 0 && fascia[len-1] == '\"') + --len; + } + char* p = iFasciaFileName; + if (fascia[0] != '\\' && (len < 3 || fascia[1] != ':')) + { + //relative path + strcpy(p, Property::GetString("EmulatorDataPath")); + p += strlen(p); + } + memcpy(p, fascia, len); + p[len] = '\0'; + } + else + { + // default to machine name + strcpy(iFasciaFileName, Property::GetString("EmulatorDataPath")); + strcat(iFasciaFileName, Property::GetString("MachineName")); + strcat(iFasciaFileName, ".bmp"); + } + return KErrNone; + } + +TViewport::TViewport() + :iScreenProps(NULL),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0) + { + } + +TViewport::TViewport(DScreenProperties* aScreenProps) + :iScreenProps(aScreenProps),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0) + { + } +TViewport::~TViewport() + { + } + + +/** +Changes the logical position of the viewport within the input area +of the emulator screen. The method may adjust the position so that +the viewport stays within the input area. +@param aPosition The new Y position of the top left hand corner of the viewport. +@param aHwnd The window associated with the viewport +*/ +void TViewport::ScrollToY(TInt aPosition, HWND aHwnd) + { + + SCROLLINFO scrollinfo; + scrollinfo.cbSize=sizeof(scrollinfo); + + //save for later + scrollinfo.fMask=SIF_POS; + GetScrollInfo(aHwnd, SB_VERT, &scrollinfo); + TInt oldY=scrollinfo.nPos; + + if(aPosition<0) + { + scrollinfo.nPos = 0; + } + else if( (aPosition+GetViewportHeight())>GetMaxHeight()) + { + scrollinfo.nPos = max(0,GetMaxHeight() - GetViewportHeight() ); + } + else + { + scrollinfo.nPos=aPosition; + } + + SetViewportOffsetY(scrollinfo.nPos); + scrollinfo.fMask=SIF_POS; + SetScrollInfo(aHwnd,SB_VERT, &scrollinfo, TRUE ); + ScrollWindowEx(aHwnd, 0, oldY-scrollinfo.nPos, 0, 0, NULL, NULL, SW_INVALIDATE); + + UpdateChildPos(aHwnd); + } + +/** +As for ScrollToY but for the X direction +*/ +void TViewport::ScrollToX(TInt aPosition, HWND aHwnd) + { + SCROLLINFO scrollinfo; + scrollinfo.cbSize=sizeof(scrollinfo); + + //save for later + scrollinfo.fMask=SIF_POS; + GetScrollInfo(aHwnd, SB_HORZ, &scrollinfo); + TInt oldX=scrollinfo.nPos; + + if(aPosition<0) + { + scrollinfo.nPos = 0; + } + else if( (aPosition+GetViewportWidth())>GetMaxWidth()) + { + scrollinfo.nPos = max(0,GetMaxWidth() - GetViewportWidth() ); + } + else + { + scrollinfo.nPos=aPosition; + } + + SetViewportOffsetX(scrollinfo.nPos); + scrollinfo.fMask=SIF_POS; + SetScrollInfo(aHwnd,SB_HORZ, &scrollinfo, TRUE ); + ScrollWindowEx(aHwnd, oldX-scrollinfo.nPos, 0, 0, 0, NULL, NULL, SW_INVALIDATE); + + UpdateChildPos(aHwnd); + } + +//Forward declaration +LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin); + +/** +Move the child window to it's correct position. + +@param aHwnd The HWND of the parent window +*/ +void TViewport::UpdateChildPos(HWND aHwnd) + { + TInt screenNumber = ::ScreenFromHWND(aHwnd,TheWin); + HWND childWin = TheChildWin[screenNumber]; + + switch (iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + MoveWindow( + childWin, + iScreenProps->iScreenOffsetX - GetViewportOffsetX(), + iScreenProps->iScreenOffsetY - GetViewportOffsetY(), + iScreenProps->iScreenWidth, + iScreenProps->iScreenHeight, + TRUE + ); + break; + case EEmulatorFlipInvert: + MoveWindow( + childWin, + iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth) - GetViewportOffsetX(), + iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetY(), + iScreenProps->iScreenWidth, + iScreenProps->iScreenHeight, + TRUE + ); + break; + case EEmulatorFlipLeft: + MoveWindow( + childWin, + iScreenProps->iScreenOffsetY - GetViewportOffsetX(), + iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth)- GetViewportOffsetY(), + iScreenProps->iScreenHeight, + iScreenProps->iScreenWidth, + TRUE + ); + break; + case EEmulatorFlipRight: + MoveWindow( + childWin, + iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetX(), + iScreenProps->iScreenOffsetX - GetViewportOffsetY(), + iScreenProps->iScreenHeight, + iScreenProps->iScreenWidth, + TRUE + ); + break; + } + + } + +/** +Update the range of the horizontal scrollbar, +to take account of the current viewport width. + +@param aHwnd The window to be updated +*/ +void TViewport::UpdateScrollBarH(HWND aHwnd) + { + + SCROLLINFO scrollinfoHor; + scrollinfoHor.cbSize=sizeof(scrollinfoHor); + scrollinfoHor.fMask=SIF_RANGE|SIF_PAGE; + scrollinfoHor.nMin=0; + scrollinfoHor.nMax= GetMaxWidth()-1; + + + TInt newPage = GetViewportWidth() ; + TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image. + if ( newPage>= scrollinfoHor.nMax -GetSystemMetrics(SM_CXVSCROLL) + && newPage < scrollinfoHor.nMax+1) + { + redraw=ETrue; + newPage=GetMaxWidth(); + + } + scrollinfoHor.nPage= newPage; + + SetScrollInfo(aHwnd,SB_HORZ, &scrollinfoHor, TRUE ); + if(redraw) + { + ScrollToX(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar + InvalidateRect(aHwnd, NULL, TRUE); + } + } + +/** +Update the range of the vertical scrollbar, +to take account of the current viewport width. + +@param aHwnd The window to be updated +*/ +void TViewport::UpdateScrollBarV(HWND aHwnd) + { + SCROLLINFO scrollinfoVer; + scrollinfoVer.cbSize=sizeof(scrollinfoVer); + scrollinfoVer.fMask=SIF_RANGE|SIF_PAGE; + scrollinfoVer.nMin=0; + scrollinfoVer.nMax= GetMaxHeight()-1; + + TInt newPage = GetViewportHeight() ; + TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image. + if ( newPage>= scrollinfoVer.nMax -GetSystemMetrics(SM_CYHSCROLL) + && newPage < scrollinfoVer.nMax+1) + { + redraw=ETrue; + newPage=GetMaxHeight(); + } + scrollinfoVer.nPage= newPage; + + SetScrollInfo(aHwnd,SB_VERT, &scrollinfoVer, TRUE ); + if(redraw) + { + ScrollToY(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar + InvalidateRect(aHwnd, NULL, TRUE); + } + } + +/** +Returns the max width for the viewport window (non-client area) so that it +may be bounded. Takes account of scrollbar. + +@return Max width +*/ +TInt TViewport::GetMaxWindowWidth() const + { + + RECT rect = {0,0,0,0}; + + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + rect.right=iScreenProps->iXYInputWidth; + rect.bottom=iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + rect.right=iScreenProps->iXYInputHeight; + rect.bottom=iScreenProps->iXYInputWidth; + break; + } + } + AdjustWindowRect(//take account of window decorations + &rect, + KWinStyle, + FALSE + ); + + + return (rect.right-rect.left); + } + +/** +Returns the max height for the viewport window (non-client area) so that it +may be bounded. Takes account of scrollbar. + +@return Max height +*/ +TInt TViewport::GetMaxWindowHeight() const + { + + RECT rect ={0,0,0,0}; + + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + rect.right=iScreenProps->iXYInputWidth; + rect.bottom=iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + rect.right=iScreenProps->iXYInputHeight; + rect.bottom=iScreenProps->iXYInputWidth; + break; + } + } + AdjustWindowRect(//take account of window decorations + &rect, + KWinStyle, + FALSE + ); + return (rect.bottom-rect.top); + } + +/** +Returns the maximum width for the viewport (client area only). +Allowing for the orientation of the emulator. + +@return Max width +*/ +TInt TViewport::GetMaxWidth() const + { + TInt width=0; + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + width = iScreenProps->iXYInputWidth; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + width = iScreenProps->iXYInputHeight; + break; + } + } + + return width; + } + +/** +Returns the maximum height for the viewport (client area only). +Allowing for the orientation of the emulator. + +@return Max height +*/ +TInt TViewport::GetMaxHeight() const + { + TInt height=0; + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + height = iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + height = iScreenProps->iXYInputWidth; + break; + } + } + + return height; + + } + +/** +Sets the X offset of the viewport from the edge of the input area +@param aOffset The X offset +*/ +void TViewport::SetViewportOffsetX(TInt aOffset) + { + iViewportOffsetX = aOffset; + } + +/** +Sets the Y offset of the viewport from the edge of the input area +@param aOffset The Y offset +*/ +void TViewport::SetViewportOffsetY(TInt aOffset) + { + iViewportOffsetY = aOffset; + } + +TInt TViewport::GetViewportOffsetX() const + { + return iViewportOffsetX; + } +TInt TViewport::GetViewportOffsetY() const + { + return iViewportOffsetY; + } + +/** +Sets the viewport width, this is equal to the width +of the window's client area +@param aWidth The width +*/ +void TViewport::SetViewportWidth(TInt aWidth) + { + iViewportWidth=aWidth; + } + +/** +Sets the viewport height, this is equal to the height +of the window's client area +@param aHeight The height +*/ +void TViewport::SetViewportHeight(TInt aHeight) + { + iViewportHeight=aHeight; + } + +TInt TViewport::GetViewportWidth() const + { + return iViewportWidth; + } +TInt TViewport::GetViewportHeight() const + { + return iViewportHeight; + } + +// the UI class + +DWinsUi::DWinsUi() + :iVirtualKeys(10), + iControlHotKeys(10) + {} + +/// Returns the current mode's depth. Remember current mode is never set! +TUint DWinsUi::ColorDepth(TInt aScreenNumber) + { + TVideoInfoV01 info; + VideoInfo(aScreenNumber, info); + return info.iBitsPerPixel; + } + +TInt DWinsUi::SetFlip(TEmulatorFlip aFlip, TInt aScreenNumber) + { + if(TUint(aScreenNumber)>=TUint(systemIni->iScreens.Count())) + return KErrArgument; + int r1 = PostMessageA(TheChildWin[aScreenNumber],WM_FLIP_MESSAGE,(TUint)aFlip,NULL); + return r1 ? KErrNone : KErrGeneral; + } + +void DWinsUi::Info(TVariantInfoV01& aInfo) + { + aInfo.iLedCapabilities=0x3; + } + +HWND DWinsUi::HWnd() + { + return TheControlWin; + } + +TInt DWinsUi::SetupProperties(TInt aId) + +// +// load UI settings from the emulator properties +// + { + //setup the screens + TInt screens = Property::GetInt("[screens]", 1); + + for (TInt x = 0; x < screens; ++x) + { + DScreenProperties * pScr = new DScreenProperties(); + if (!pScr) + return KErrNoMemory; + + TInt ret = pScr->SetupProperties(aId,x); + if (KErrNone == ret) + ret = iScreens.Append(pScr); + + if (KErrNone != ret) + { + delete pScr; + return ret; + } + } +// + char property[50]; + wsprintfA(property, "Configuration[%d]LedSize",aId); + iLedSize = Property::GetInt(property, KLedSize); + wsprintfA(property, "Configuration[%d]LedArrangeVertically",aId); + iLedVertical = Property::GetBool(property, KLedVertical); + wsprintfA(property, "Configuration[%d]LedArrangeHorizontally",aId); + if (Property::GetBool(property)) + iLedVertical = EFalse; + wsprintfA(property, "Configuration[%d]LedOffsetX",aId); + iLedOffsetX = Property::GetInt(property, KLedLeft); + wsprintfA(property, "Configuration[%d]LedOffsetY",aId); + iLedOffsetY = Property::GetInt(property, KLedTop); + wsprintfA(property, "Configuration[%d]LedGap",aId); + iLedGap = Property::GetInt(property, KLedGap); +// + wsprintfA(property, "Configuration[%d]PointerType",aId); + const char* pointer = Property::GetString(property, "Pen"); + if (_stricmp(pointer, "None") == 0) + { + iPointerType=_S8("NONE"); + iXYInputType=EXYInputNone; + } + else if (_stricmp(pointer,"Pen") == 0) + { + iPointerType=_S8("PEN"); + iXYInputType=EXYInputPointer; + } + else if (_stricmp(pointer,"Mouse") == 0) + { + iPointerType=_S8("MOUSE"); + iXYInputType=EXYInputMouse; + } + else if (_stricmp(pointer,"Delta-Mouse") == 0) + { + iPointerType=_S8("MOUSE"); + iXYInputType=EXYInputDeltaMouse; + } + else + return KErrArgument; +// + wsprintfA(property, "Configuration[%d]DigitizerOffsetX",aId); + iDigitizerOffsetX = Property::GetInt(property, -iScreens[0]->iScreenOffsetX); + wsprintfA(property, "Configuration[%d]DigitizerOffsetY",aId); + iDigitizerOffsetY = Property::GetInt(property, -iScreens[0]->iScreenOffsetY); + wsprintfA(property, "Configuration[%d]DigitizerWidth",aId); + iDigitizerWidth = Property::GetInt(property,-1); + wsprintfA(property, "Configuration[%d]DigitizerHeight",aId); + iDigitizerHeight = Property::GetInt(property,-1); + wsprintfA(property, "Configuration[%d]DisableDigitizer",aId); + iDigitizerEnabled = !Property::GetBool(property); +// To enable the multitouch + wsprintfA(property, "EnableMultiTouch"); + iMultiTouchEnabled = Property::GetBool(property,EFalse); + wsprintfA(property, "SYMBIAN_BASE_USE_GCE"); + iGCEEnabled = Property::GetBool(property,EFalse); + wsprintfA(property, "MultiTouchProximityStep"); + iMultiTouchProximityStep = Property::GetInt(property,-1); + wsprintfA(property, "MultiTouchPressureStep"); + iMultiTouchPressureStep = Property::GetInt(property,-1); +// + strcpy(iSysIniFileName, Property::GetString("EmulatorDataPath")); + strcat(iSysIniFileName, "emulator\\"); + if (!Emulator::CreateAllDirectories(iSysIniFileName)) + return Emulator::LastError(); + strcat(iSysIniFileName, Property::GetString("MachineName")); + strcat(iSysIniFileName, ".sys.ini"); +// + TInt r = iKeyboard.Init(aId); + if (r != KErrNone) + return r; + + wsprintfA(property, "Configuration[%d]VirtualKey",aId); + r = MultiProperty(&DWinsUi::DoDefineVirtualKey, this, property); + if (r != KErrNone) + return r; +// + + wsprintfA(property, "Configuration[%d]NoVersionInfo",aId); + iDisplayVersionInfo = !Property::GetBool(property); + + wsprintfA(property, "Configuration[%d]WindowTitle",aId); + const char * p = Property::GetString(property); + if (p && (strlen(p) <= KMaxNameSize)) + strcpy(iWindowTitle, p); + else + strcpy(iWindowTitle, DefaultWindowTitle); + + if (iDisplayVersionInfo) + { + TInt wtLen = strlen(iWindowTitle); + TInt vtLen = strlen(VersionText); + if ((wtLen + vtLen) > KMaxNameSize) + iWindowTitle[KMaxNameSize-vtLen] = '\0'; + strcat(iWindowTitle, VersionText); + } + + wsprintfA(property, "Configuration[%d]OnActivation",aId); + pointer = Property::GetString(property); + //example OnActivation 270 EKeyScreenDimension1 + //params are rotation(int) and key(string) + if (pointer) + { + char * next; + + //skip any white space + const char* beg = skipws(pointer); + + //get the number + long rotation = strtol(beg, &next, 0); + if (next == beg) + return KErrArgument; + + switch (rotation) + { + case 0: + iScreens[0]->iScreenRotation = EEmulatorFlipRestore; + break; + case 90: + iScreens[0]->iScreenRotation = EEmulatorFlipRight; + break; + case 180: + iScreens[0]->iScreenRotation = EEmulatorFlipInvert; + break; + case 270: + iScreens[0]->iScreenRotation = EEmulatorFlipLeft; + break; + default: + r = KErrArgument; + } + if (r != KErrNone) + return r; + + beg = skipws(next); + + //beg should now point to the keycode + TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, strlen(beg))); + if (key == KErrNotFound) + return key; + iInitialFlipMsg = key; + } + + //EmulatorControl messages are a bit like virtual keys + wsprintfA(property, "Configuration[%d]EmulatorControl",aId); + r = MultiProperty(&DWinsUi::DoDefineEmulatorControl, this, property); + if (r != KErrNone) + return r; + + wsprintfA(property, "Configuration[%d]EmulatorControlHotKey",aId); + r = MultiProperty(&DWinsUi::DoDefineEmulatorControlHotKey, this, property); + if (r != KErrNone) + return r; + + return KErrNone; + } + +TInt DWinsUi::NumberOfScreens() + { + return iScreens.Count(); + } + +/** +Return the highest bit depth from an emulator mode mask. +@param aModeMask A bitwise combination of KEmul... display mode mask values. +@return A color depth in bits per pixel. +*/ +LOCAL_C TInt MaximumBitDepthFromMask(TInt aModeMask) + { + // Choose the highest bits per pixel based on the display mode mask. + if (aModeMask & KEmulColor16M) + { + return 24; + } + if (aModeMask & KEmulColor64K) + { + return 16; + } + if (aModeMask & KEmulColor4K) + { + return 12; + } + + // Lower bit depths are not supported, so use the default + return 24; + } + + +/** +Return the TDisplayRotation corresponding to the given TEmulatorFlip. +@param aFlip A screen rotation as a TEmulatorFlip. +@return The screen rotation as a TDisplayRotation. +*/ +LOCAL_C RDisplayChannel::TDisplayRotation FlipToDisplayRotation(TEmulatorFlip aFlip) + { + switch (aFlip) + { + case EEmulatorFlipLeft: + return RDisplayChannel::ERotation90CW; + case EEmulatorFlipInvert: + return RDisplayChannel::ERotation180; + case EEmulatorFlipRight: + return RDisplayChannel::ERotation270CW; + } + return RDisplayChannel::ERotationNormal; + } + + +TInt DWinsUi::SetDisplayChannel(TInt aScreenNumber, DDisplayChannel* aDisplay) + { + return systemIni->SetDisplayChannelImpl(aScreenNumber,aDisplay); + } + + +TInt DWinsUi::SetDisplayChannelImpl(TInt aScreenNumber, DDisplayChannel* aDisplay) + { + if (TUint(aScreenNumber) >= TUint(NumberOfScreens())) + { + // Screen number is either negative or too big. + return KErrArgument; + } + + TInt r = KErrNone; + HWND hWnd = TheChildWin[aScreenNumber]; + TBufferSet& buffer = masterIni->iBufferSet[aScreenNumber]; + + if (aDisplay) + { + // Display driver connecting + DScreenProperties* screen = iScreens[aScreenNumber]; + RDisplayChannel::TDisplayInfo info; + + TInt pixelBytes = 2; + info.iBitsPerPixel = MaximumBitDepthFromMask(screen->iColorDepth); + + switch (info.iBitsPerPixel) + { + case 12: // XRGB4444 + info.iPixelFormat = EUidPixelFormatXRGB_4444; + break; + case 16: // RGB565 + info.iPixelFormat = EUidPixelFormatRGB_565; + break; + default: + // Force anything else to packed RGB888 + pixelBytes = 4; + info.iBitsPerPixel = 24; + info.iPixelFormat = EUidPixelFormatXRGB_8888; + break; + } + + TInt width = screen->iMaxScreenWidth; + TInt height = screen->iMaxScreenHeight; + + info.iRefreshRateHz = screen->iRefreshRateHz; + info.iAvailableRotations = RDisplayChannel::ERotationNormal | RDisplayChannel::ERotation90CW | + RDisplayChannel::ERotation180 | RDisplayChannel::ERotation270CW; + info.iNormal.iWidth = width; + info.iNormal.iHeight = height; + // Windows requires rounding up to 4-bytes words + info.iNormal.iOffsetBetweenLines = _ALIGN_UP(width * pixelBytes, 4); + info.iFlipped.iWidth = height; + info.iFlipped.iHeight = width; + // Windows requires rounding up to 4-bytes words + info.iFlipped.iOffsetBetweenLines = _ALIGN_UP(height * pixelBytes, 4); + + TInt maxSize=0; + //ensure legacy buffer is large enough for all supported modes. + //It would be a very strange setup for the max size to not be the max bpp, + //but we don't know which mode is max bpp anyway! + TVideoInfoV01 videoInfo; + for (TInt mode=0,maxMode=screen->iMaxModes;modeVideoInfoForDisplayDriver(aScreenNumber,mode, videoInfo)) //can't actually fail currently + { + TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iHeight; + if (dwSize>maxSize) + maxSize=dwSize; + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + //rotated mode may use more RAM?? Height may be >Width or may not be a multiple of stride quantum + if (systemIni->VideoInfoForDisplayDriver(aScreenNumber,mode|KModeFlagFlipped, videoInfo)) //can't actually fail currently + { + TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iWidth; + if (dwSize>maxSize) + { + maxSize=dwSize; + } + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + } + + masterIni->iMaxSizeInBytes = maxSize; + if (__e32_atomic_add_ord32(&buffer.iDisplayDriverCount, 1) == 0) + { + // First driver to connect, allocate frame buffers. + // +1 frame buffer is ui legacy buffer at [0], so does need to take account of stride and offset + r = masterIni->AllocateFrameBuffers(aScreenNumber, screen->iCompositionBuffers + 1, maxSize); + } + + if (r == KErrNone) + { + buffer.iScreenBuffer.iDisplayBufferOffset = 0; + masterIni->iBufferSet[aScreenNumber].iDisplayChannel = aDisplay; + masterIni->InitBitmapHeader(*screen, &buffer.iInfo); + masterIni->InitBufferFormat(*screen, buffer.iBufferFormat); + if(systemIni->VideoInfoForDisplayDriver(aScreenNumber,screen->iCurrentMode, videoInfo, ETrue)) + { + r = aDisplay->Initialize(info, + FlipToDisplayRotation(screen->iScreenRotation), + hWnd, buffer.iScreenBuffer.iFrameBuffers, + buffer.iScreenBuffer.iMemChunks, + buffer.iDsaBuffer, + videoInfo.iSizeInPixels,videoInfo.iSizeInTwips, + masterIni->iSupportedPixelFormatTable, + masterIni->iSupportedPixelFormatTableSize, + buffer.iBufferFormat); + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + } + + if (r != KErrNone && __e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1) + { + // Release any that were allocated + masterIni->ReleaseFrameBuffers(aScreenNumber); + } + } + else + { + // Display driver disconnected + if (__e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1) + { + // All drivers disconnected, deallocate memory. + masterIni->ReleaseFrameBuffers(aScreenNumber); + } + } + + return r; + } + + +void DWinsUi::SetVirtualKey(const TBool aProcessing, const TInt aCommandData, const TEmulCommand aCommand) + { + iProcessingVirtualKey = aProcessing; + iFakedVirtualKey = aCommandData; + iVirtualKeyCommand = aCommand; + } + +TBool DWinsUi::WasVirtualKey(TInt& aCommandData, TEmulCommand& aCommand) + { + if (iProcessingVirtualKey) + { + + aCommandData = iFakedVirtualKey; + aCommand = iVirtualKeyCommand; + } + return iProcessingVirtualKey; + } + + +TInt DWinsUi::DoDefineEmulatorControl(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineEmulatorControl(aValue); + } + + +TInt DWinsUi::DefineEmulatorControl(const char* aValue) + { + + //example EmulatorControl SelectConfig 2 rect 223,640 29,22 + //example EmulatorControl NextConfig rect 223,640 29,22 + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt err = KErrNone; + + TEmulCommand command = ENoCommand; + TInt data = 0; + if (_strnicmp(beg, "SelectConfig", end-beg) == 0) + { + //get the int param which is the config to switch to + beg = end; + char * e; + data = strtol(beg, &e,0); + if (beg == e) + err = KErrArgument; + end = e; + command = ESelectConfig; + } + else if(_strnicmp(beg, "NextConfig", end-beg) == 0) + + { + command = ENextConfig; + } + else + err = KErrArgument; + + if (err != KErrNone) + return err; + + //get the shape + beg = skipws(end); + end = skiptok(beg); + if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0) + return KErrArgument; + + // get the parameters + beg = skipws(end); + char* end2; + TInt x = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt y = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + beg = skipws(end2); + TInt w = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt h = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + + VKRect* pRect = new VKRect(data, command, x, y, w, h); + if (!pRect) + return KErrNoMemory; + return iVirtualKeys.Append(pRect); + + } + + +TInt DWinsUi::DoDefineVirtualKey(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineVirtualKey(aValue); + } + +TInt DWinsUi::DefineVirtualKey(const char* aValue) + { + // Get the key to map + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, end-beg)); + if (key == KErrNotFound) + return key; + + //get the shape + beg = skipws(end); + end = skiptok(beg); + if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0) + return KErrArgument; + + // get the parameters + beg = skipws(end); + char* end2; + TInt x = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt y = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + beg = skipws(end2); + TInt w = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt h = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + + VKRect* pRect = new VKRect(key, EKey, x, y, w, h); + if (!pRect) + return KErrNoMemory; + return iVirtualKeys.Append(pRect); + } + + +LOCAL_C TInt readBitmapInfo(PBITMAPINFOHEADER aHeader, const char* aFileName) + { + PBITMAPFILEHEADER pbmfh=NULL; + PBITMAPINFOHEADER pbmih=NULL; + TInt bfOffBits; + + HANDLE fh=CreateFileA(aFileName,GENERIC_READ,NULL,NULL,OPEN_EXISTING,NULL,NULL); + if (!fh || fh==INVALID_HANDLE_VALUE) + return KErrNotFound; + + TInt r=KErrNone; + + // read in the bitmap file header. save the offset to bits. + pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER)); + if (pbmfh==NULL) + { + r=KErrNotFound; + goto exit; + } + DWORD bytesRead; + ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER), &bytesRead, NULL); + bfOffBits=pbmfh->bfOffBits; + + // read in the bitmap info header and the color table right after it. + pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER)); + if (pbmih==NULL) + { + r=KErrNotFound; + goto exit; + } + ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + *aHeader=*pbmih; +exit: + LocalFree(LocalHandle ((LPSTR)pbmih)); + LocalFree(LocalHandle ((LPSTR)pbmfh)); + CloseHandle(fh); + return r; + } + +HBITMAP readBitmap(HDC aHdc, const char* aFileName) +// +// reads a BMP file from disk and returns a HBITMAP +// + { + HBITMAP hbm=NULL; + PBITMAPFILEHEADER pbmfh=NULL; + PBITMAPINFOHEADER pbmih=NULL; + TUint8 *pBits=NULL; + TInt bfOffBits; + TInt nbytes; + + HANDLE fh=CreateFileA(aFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL); + if (!fh || fh==INVALID_HANDLE_VALUE) + return NULL; + + nbytes=GetFileSize((HANDLE)fh, NULL); + // read in the bitmap file header. save the offset to bits. + pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER)); + if (pbmfh==NULL) + goto exit; + DWORD bytesRead; + ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + bfOffBits=pbmfh->bfOffBits; + + // read in the bitmap info header and the color table right after it. + pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER)); + if (pbmih==NULL) + goto exit; + ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + + // finally read in the bit data. + pBits = (PBYTE)LocalAlloc (LPTR, (nbytes - bfOffBits)); + if (pBits==NULL) + goto exit; + ReadFile(fh, (LPVOID)pBits, nbytes-bfOffBits,&bytesRead,NULL); + + hbm=CreateDIBitmap(aHdc, pbmih, CBM_INIT, pBits,(PBITMAPINFO) pbmih, DIB_RGB_COLORS); +exit: + LocalFree(LocalHandle ((LPSTR)pBits)); + LocalFree(LocalHandle ((LPSTR)pbmih)); + LocalFree(LocalHandle ((LPSTR)pbmfh)); + CloseHandle(fh); + return hbm; + } + +void LoadFasciaBitmap(TInt aScreen) + { + HDC hdc=GetDC(TheWin[aScreen]); + RECT windowRect = {0}; + windowRect.right=systemIni->iScreens[aScreen]->iXYInputWidth; + windowRect.bottom=systemIni->iScreens[aScreen]->iXYInputHeight; + HBITMAP screenBitmap=readBitmap(hdc, systemIni->iScreens[aScreen]->iFasciaFileName); + if (screenBitmap==NULL) + { + screenBitmap=CreateCompatibleBitmap(hdc, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top); + HDC hdcMem=CreateCompatibleDC(hdc); + SelectObject(hdcMem, screenBitmap); + PatBlt(hdcMem, 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, BLACKNESS); + DeleteDC(hdcMem); + } + __ASSERT_ALWAYS(screenBitmap!=NULL,Fault(EGuiCreateBitmap)); + TheScreenBitmap[aScreen]=screenBitmap; + + DrawLeds(); + + ReleaseDC(TheWin[aScreen], hdc); + } +TBool DWinsUi::MultiTouchEnabled() const + { + return iMultiTouchEnabled; + } + +TBool DWinsUi::GCEEnabled() const + { + return iGCEEnabled; + } + +TInt DWinsUi::MultiTouchProximityStep() const + { + return iMultiTouchProximityStep; + } + +TInt DWinsUi::MultiTouchPressureStep() const + { + return iMultiTouchPressureStep; + } + +TBool DWinsUi::OnDigitizer(TInt aX, TInt aY) const + { + if (!iDigitizerEnabled) + return EFalse; + switch(CurrentFlipState[0]) + { + case EEmulatorFlipRestore: + { + aX -= iDigitizerOffsetX; + aY -= iDigitizerOffsetY; + break; + } + case EEmulatorFlipInvert: + { + aX -= systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth; + aY -= systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight; + break; + } + case EEmulatorFlipRight: + { + TInt oldY = aY; + aY = aX - (systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight); + aX = oldY - iDigitizerOffsetX; + break; + } + case EEmulatorFlipLeft: + { + TInt oldY = aY; + aY = aX - iDigitizerOffsetY; + aX = oldY - (systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth); + break; + } + } + return (TUint(aX) < TUint(iDigitizerWidth) && TUint(aY) < TUint(iDigitizerHeight)); + } + +LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos) +// +// Add a mouse event. +// + { + if (systemIni->OnDigitizer(aXpos, aYpos)) + { + TRawEvent v; + v.Set(aType,aXpos,aYpos); + TheEventQ.Add(v); + } + } + +LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos,TInt aZpos, TInt aPointerId=0) +// +// Add a multitouch mouse event. +// + { + if (systemIni->OnDigitizer(aXpos, aYpos)) + { + TRawEvent v; + v.Set(aType,aXpos,aYpos, aZpos); + v.SetPointerNumber(static_cast(aPointerId)); + TheEventQ.Add(v); + } + } +LOCAL_C void addKeyEvent(TRawEvent::TType aType,TInt aKey) + { + TRawEvent v; + v.Set(aType, aKey); + TheEventQ.Add(v); + } + + +LOCAL_C void SwitchConfiguration(TInt aData, TBool aSendFlipKey = ETrue) + { + if (aData < 0 || aData >= masterIni->iSystemInis.Count()) + return; + + CurrentConfiguration = aData; + systemIni = masterIni->iSystemInis[aData]; + + //get the correct fascia bitmaps + TInt screens=systemIni->iScreens.Count(); + TInt i; + TUint disabledWinType=ENormalResolution; + for(i=0;iiBufferSet[i].iDisplayState!=ENormalResolution) + { + disabledWinType=masterIni->iBufferSet[i].iDisplayState; + } + } + + //update the window title + if (disabledWinType!=ENormalResolution && disabledWinType < 4) //hardwired 4 because the code below is hardwired + { //string may be multi-part indexed by disable type, or it may not + CHAR* firstsemi=strchr(systemIni->iWindowTitle,';'); + CHAR* secondsemi=NULL; + if (firstsemi) + { + secondsemi=strchr(firstsemi+1,';'); + } + if (firstsemi&&secondsemi) + { + *firstsemi='\0'; + *secondsemi='\0'; + char* ptr[4]={0,systemIni->iWindowTitle,firstsemi+1,secondsemi+1}; + SetWindowTextA(TheControlWin, ptr[disabledWinType]); + *firstsemi=';'; + *secondsemi=';'; + } + else + { + SetWindowTextA(TheControlWin, systemIni->iWindowTitle); + } + + } + else + { + SetWindowTextA(TheControlWin, systemIni->iWindowTitle); + } + //resize and repaint the current window anyway. + //the text window server doesn't respond to orientation messages + for(i=0;iiScreens[i]->iScreenRotation,0); + } + + //pass on the orientation key to the windows server + if (aSendFlipKey) + { + if (!WinsGuiPowerHandler->iStandby) + { + addKeyEvent(TRawEvent::EKeyDown, systemIni->iInitialFlipMsg); + addKeyEvent(TRawEvent::EKeyUp, systemIni->iInitialFlipMsg); + } + else + { + //remember the flip message so we can send it to the window server when we come out of standby + SavedFlipMessage = systemIni->iInitialFlipMsg; + } + } + } +/** +Sets the specified screen to the given width and height, if available. + +The configurations are searched to find a match, taking the display state into +account. If no configuration is available, the request is ignored. + +@param aScreenNumber the screen index +@param aWidth the desired width +@param aHeight the desired height +**/ +void DMasterIni::SetDisplaySize(TInt aDisplayNumber, TInt aWidth, TInt aHeight) + { + TInt displayCount = iBufferSet.Count(); + + if (aDisplayNumber < 0 || aDisplayNumber >= displayCount) + { + // Invalid screen number, discard. + return; + } + + if (iBufferSet[aDisplayNumber].iDisplayState != ENormalResolution) + { + // No (non-zero) resolutions available, discard. + return; + } + + TInt count = iSystemInis.Count(); + TInt index; + for (index = 0; index < count; index++) + { + DWinsUi* newIni = masterIni->iSystemInis[index]; + DScreenProperties* newProps = newIni->iScreens[aDisplayNumber]; + + if (newProps->iScreenWidth == aWidth && newProps->iScreenHeight == aHeight) + { + // Found a potential match. Check other screens match their current size. + if (newIni == systemIni) + { + // Current configuration, already in use. Nothing to do. + break; + } + + TInt display; + for (display = 0; display < displayCount; display++) + { + if (display == aDisplayNumber) + { + // No need to check the display we are changing + continue; + } + + DScreenProperties* currentPropsN = systemIni->iScreens[display]; + DScreenProperties* newPropsN = newIni->iScreens[display]; + + if (newPropsN->iScreenWidth != currentPropsN->iScreenWidth || + newPropsN->iScreenHeight != currentPropsN->iScreenHeight) + { + // Resolution mismatch, try next configuration. + break; + } + } + + if (display == displayCount) + { + // Match found, switch to this configuration and stop. Force + // rotation to the same as the current rotation. + newProps->iScreenRotation = systemIni->iScreens[aDisplayNumber]->iScreenRotation; + SwitchConfiguration(index); + break; + } + } + } + } + + +void DMasterIni::SetBufferFormat(TInt aDisplayNumber, TUint aAggregateSize, RDisplayChannel::TPixelFormat aPixelFormat) + { + TInt displayCount = iBufferSet.Count(); + + if (aDisplayNumber < 0 || aDisplayNumber >= displayCount) + { + // Invalid screen number, discard. + return; + } + + LPBITMAPV4HEADER info = &iBufferSet[aDisplayNumber].iInfo; + + // update the bitmap header taking in consideration the new pixel format + switch (aPixelFormat) + { + case EUidPixelFormatXRGB_4444: + case EUidPixelFormatARGB_4444: + info->bV4BitCount=16; + info->bV4V4Compression = BI_BITFIELDS; + info->bV4RedMask = 0x0F00; + info->bV4GreenMask = 0x00F0; + info->bV4BlueMask = 0x000F; + break; + case EUidPixelFormatRGB_565: + info->bV4BitCount=16; + info->bV4V4Compression = BI_BITFIELDS; + info->bV4RedMask = 0xF800; + info->bV4GreenMask = 0x07E0; + info->bV4BlueMask = 0x001F; + break; + case EUidPixelFormatXRGB_8888: // Really 32bpp, but top 8 unused + case EUidPixelFormatARGB_8888: + case EUidPixelFormatARGB_8888_PRE: + info->bV4BitCount=32; + info->bV4V4Compression = BI_RGB; + // Mask is implicit for BI_RGB compression + break; + default: + // We got an error, it seems. Let's ignore the message + return; + } + iBufferSet[aDisplayNumber].iBufferFormat.iPixelFormat = aPixelFormat; + + // taking advantage of limiting the width and size to KMaxTInt16 + TInt width = aAggregateSize & 0x0000ffff; + TInt height = (aAggregateSize >> 16) & 0x0000ffff; + + // let's deal with the new size just received + iBufferSet[aDisplayNumber].iBufferFormat.iSize.iWidth = width; + iBufferSet[aDisplayNumber].iBufferFormat.iSize.iHeight = height; + + // update the bitmap header, taking in consideration the rotation + switch (CurrentFlipState[aDisplayNumber]) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + info->bV4Width = width; + info->bV4Height = -height; + break; + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + info->bV4Width = height; + info->bV4Height = -width; + break; + } + // finally, update the image size + SetImageSize(aDisplayNumber); + } + +void DMasterIni::SetImageSize(TInt aScreenNumber) + { + TInt displayCount = iBufferSet.Count(); + + if (aScreenNumber >= 0 && aScreenNumber < displayCount) + { + LPBITMAPV4HEADER info = &iBufferSet[aScreenNumber].iInfo; + TInt bpp = _ALIGN_UP(info->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32 + TInt widthInBpp = info->bV4Width * bpp; + //rounding to 32 bits (4 octets) and converting, then, bits to octets; + TInt scanLineInBytes = _ALIGN_UP(widthInBpp, 32) >> 3; + // info->bV4Height is negative or zero + info->bV4SizeImage = -info->bV4Height * scanLineInBytes; + } + } + +LOCAL_C void NextConfiguration() + { + TInt config = CurrentConfiguration; + if (++config == masterIni->iSystemInis.Count()) + config = 0; + SwitchConfiguration(config); + } + + + +LOCAL_C TBool ProcessedByEmulatorKey(TInt aScanCode, HWND hWnd,TUint message,TUint wParam,TUint lParam) + { + + TBool rVal = EFalse; + rVal = ETrue; + for (TInt i=0;iiControlHotKeys.Count();i++)//check key combinations + { + if (systemIni->iControlHotKeys[i]->CheckCombinationPressed()) + { + switch (systemIni->iControlHotKeys[i]->iCommand) + { + + case ENextConfig: + NextConfiguration(); + break; + + case ESelectConfig: + SwitchConfiguration(systemIni->iControlHotKeys[i]->iData); + break; + + } + return ETrue; + } + } + switch (aScanCode) + { + + case EStdKeyF4: + { + // Simulate a change of media card + TInt irq = NKern::DisableAllInterrupts(); + if (*Wins::MediaDoorOpenPtr()) + { + *Wins::CurrentPBusDevicePtr() += 1; + if (*Wins::CurrentPBusDevicePtr() == 2) + { + *Wins::CurrentPBusDevicePtr() = -1; + } + } + NKern::RestoreInterrupts(irq); + + // pass on to the windows system so that if + // Alt-F4 is pressed the window will close + if (hWnd) + DefWindowProcA(hWnd,message,wParam,lParam); + break; + } + + default: + rVal = EFalse; + break; + } + return rVal; + } + +LOCAL_C void MultiChildWndPointer(TUint aMessage,TInt aXpos,TInt aYpos, TInt aZ, TInt aPointerId) +// +// Handle a multi-touch pointer event in the Symbian OS screen window +// + { + TRawEvent::TType eventType=TRawEvent::ENone; + CHAR buf[50]; + + if (aZ <= TheMultiTouch->iZMaxRange) //negative + { + eventType = TRawEvent::EPointer3DOutOfRange; + wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("Out Of Range")); + SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf)); + } + else + { + wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("%d: %d,%d,%d"), aPointerId, aXpos,aYpos,aZ); + SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf)); + switch (aMessage) + { + case WM_MOUSEMOVE: + { + eventType=TRawEvent::EPointerMove; + break; + } + case WM_LBUTTONDOWN: + { + SetCapture(TheChildWin[0]); + eventType = TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + { + ReleaseCapture(); + eventType = TRawEvent::EButton1Up; + break; + } + case WM_RBUTTONDOWN: + { + eventType = TRawEvent::EButton3Down; + break; + } + case WM_RBUTTONUP: + { + eventType = TRawEvent::EButton3Up; + break; + } + case WM_MOUSEWHEEL: + { + eventType = TRawEvent::EPointerMove; + break; + } + default: + return; + } + } + + if (!WinsGuiPowerHandler->iStandby) + { + addMouseEvent(eventType, aXpos, aYpos, aZ, aPointerId); + } + } + +LOCAL_C void ChildWndPointer(TUint message,TInt aXpos,TInt aYpos) +// +// Handle a pointer event in the Symbian OS screen window +// + { + // Enable the multitouch if the cursor is inside the main client window + if (DMultiTouch::iMultiTouchCreated) + { + RECT client; + WINDOWINFO info; + GetWindowInfo(TheChildWin[0], &info); + POINT pt = {aXpos+(TInt)info.rcClient.left, aYpos+(TInt)info.rcClient.top}; + if (GetWindowRect(TheChildWin[0], &client) && + (PtInRect(&client,pt)!=NULL) && !DMultiTouch::iMultiTouchTempEnabled) // within the window + { + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled()) + { + if(TheMultiTouch->Register()) // Register successfully + { + DMultiTouch::iMultiTouchTempEnabled = TRUE; + //Show the status bars at the bottom of the emulator + SetWindowPos(hwndStatus,0,0,0,0,0,SWP_SHOWWINDOW); + SetFocus(TheWin[0]); + SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512))); + } + } + } + } + TRawEvent::TType eventType=TRawEvent::ENone; + switch (message) + { + case WM_MOUSEMOVE: + eventType=TRawEvent::EPointerMove; + break; + case WM_LBUTTONDOWN: + { + SetCapture(TheChildWin[0]); + eventType=TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + ReleaseCapture(); + eventType=TRawEvent::EButton1Up; + break; + case WM_RBUTTONDOWN: + eventType=TRawEvent::EButton3Down; + break; + case WM_RBUTTONUP: + eventType=TRawEvent::EButton3Up; + break; + case WM_MBUTTONDOWN: + eventType=TRawEvent::EButton2Down; + break; + case WM_MBUTTONUP: + eventType=TRawEvent::EButton2Up; + break; + } + if (!WinsGuiPowerHandler->iStandby) + { + addMouseEvent(eventType, aXpos, aYpos); + } + } + +LOCAL_C void FrameWndPointer(TUint message,TInt aXpos,TInt aYpos, TInt aScreenNumber, TInt aPointerId = 0) +// +// Handle a frame wnd pointer event. +// + { + static bool processingScreenOn=FALSE; + TEmulCommand command = ENoCommand; + TInt commandData = 0; + TBool mouseEvent = ETrue; + + TRawEvent::TType eventType=TRawEvent::ENone; + + TViewport& viewport = systemIni->iScreens[aScreenNumber]->iViewport; + aXpos += viewport.GetViewportOffsetX(); // make mouse-coords relative to fascia edge even if window is scrolled + aYpos += viewport.GetViewportOffsetY(); + + switch (message) + { + case WM_MOUSEMOVE: + { + TInt newX, newY; + systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY); + + if (aPointerId == 0) + { // only system pointer changes shape + if (systemIni->GetVirtualKey(command, newX, newY) >= 0) + { + HMODULE hmodule = GetModuleHandleA("winsgui.dll"); + SetCursor(LoadCursorA((HINSTANCE)hmodule,MAKEINTRESOURCEA(OVERKEY))); //hand cursor + } + else + SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512))); //ICD_ARROW + } + + eventType=TRawEvent::EPointerMove; + + } + break; + case WM_LBUTTONDOWN: + { + SetCapture(TheWin[0]); + //check the configuration + TInt newX, newY; + + //if the emulator screen is rotated, rotate/flip the current mouse cursor position + //so it can be checked to see if it is in a key region. + systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY); + commandData = systemIni->GetVirtualKey(command, newX, newY); + + if (commandData >= 0) + { + eventType=TRawEvent::EKeyDown; + mouseEvent = EFalse; + systemIni->SetVirtualKey(ETrue, commandData, command); + } + else + eventType=TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + ReleaseCapture(); + if (processingScreenOn) + { + // ignore button up - button down was switching things on + processingScreenOn=FALSE; + return; + } + if (systemIni->WasVirtualKey(commandData, command)) + { + eventType=TRawEvent::EKeyUp; + mouseEvent = EFalse; + systemIni->SetVirtualKey(EFalse, EStdKeyNull, ENoCommand); + } + else + eventType=TRawEvent::EButton1Up; + break; + case WM_RBUTTONDOWN: + eventType=TRawEvent::EButton3Down; + break; + case WM_RBUTTONUP: + eventType=TRawEvent::EButton3Up; + break; + case WM_MBUTTONDOWN: + eventType=TRawEvent::EButton2Down; + break; + case WM_MBUTTONUP: + eventType=TRawEvent::EButton2Up; + break; + } + if (mouseEvent) + { + + if (!WinsGuiPowerHandler->iStandby) + { + /* + mouse events are relative to the child window position + and are clipped to the digitzer region in addMouseEvent + so all the mouse clicks are passed on here after being translated + to the child window coordinate system (under the current rotation) + */ + TInt newX, newY; + switch (CurrentFlipState[0]) + { + case EEmulatorFlipRestore: + default: + newX = aXpos - systemIni->iScreens[0]->iScreenOffsetX; + newY = aYpos - systemIni->iScreens[0]->iScreenOffsetY; + break; + case EEmulatorFlipInvert: + newX = aXpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX); + newY = aYpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY); + break; + case EEmulatorFlipLeft: + newX = aXpos - systemIni->iScreens[0]->iScreenOffsetY; + newY = aYpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX); + break; + case EEmulatorFlipRight: + newX = aXpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY); + newY = aYpos - systemIni->iScreens[0]->iScreenOffsetX; + break; + } + addMouseEvent(eventType, newX, newY); + } + } + else if ((((message == WM_LBUTTONDOWN && command == EKey) && !ProcessedByEmulatorKey((TUint8)commandData,0,0,0,0))) + || (message == WM_LBUTTONUP)) + { + switch (command) + { + case EKey: + if (!WinsGuiPowerHandler->iStandby) + addKeyEvent(eventType, (TUint8)commandData); + break; + + case ENextConfig: + NextConfiguration(); + break; + + case ESelectConfig: + SwitchConfiguration(commandData); + break; + } + } + } + +LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin) + { + TInt screens=systemIni->iScreens.Count(); + TInt r=-1; + for(TInt i=0;iUnRegister()) + { + SetWindowPos(hwndStatus,0,0,0,0,0,SWP_HIDEWINDOW); + } + } + FrameWndPointer(message, aXpos-info.rcClient.left, aYpos-info.rcClient.top, 0, aPointerId); + } + } + } + } + +LOCAL_C DScreenProperties* ScreenPropsFromHWND(HWND aHwnd, HWND* pWin) + { + TInt screenNumber = ScreenFromHWND(aHwnd, pWin); + + if(screenNumber >=0) + { + return systemIni->iScreens[screenNumber]; + } + return NULL; + + } + + +TInt APIENTRY childWinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The child window function. +// + { + TInt screenNumber = 0; + TRawEvent v; + switch (message) + { + case WM_FLIP_MESSAGE: // pass the flip message onto the parent window + { + screenNumber =ScreenFromHWND(hWnd,TheChildWin); + if(TUint(screenNumber) < TUint(systemIni->iScreens.Count())) + PostMessageA(TheWin[screenNumber],WM_FLIP_MESSAGE,wParam,NULL); + break; + } + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + { + if (DMultiTouch::iMultiTouchTempEnabled) + { + DMultiTouch::iMultiTouchTempEnabled = FALSE; + } + screenNumber=ScreenFromHWND(hWnd,TheChildWin); + if(screenNumber==0) + { + ChildWndPointer(message,(TInt16)(lParam&0xFFFF),(TInt16)((lParam>>16)&0xFFFF)); + } + break; + } + case WM_PAINT: + if (!PaintWindowFromBuffer(hWnd)) + { + // Original behaviour + ValidateRect(hWnd,NULL); + v.Set(TRawEvent::ERedraw); + TheEventQ.Add(v); + } + break; + case WM_ACTIVATE: + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + case WM_SYSKEYUP: + case WM_KEYUP: + Fault(EGuiChildWinProc); + break; + case WM_DESTROY: + break; + + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + break; + + case WMU_SET_DISPLAY_BUFFER: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + if (TUint(screenNumber) < TUint(systemIni->iScreens.Count())) + { + masterIni->iBufferSet[screenNumber].iDisplayBuffer = (LPVOID)lParam; + } + break; + case WMU_SET_DISPLAY_SIZE: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + masterIni->SetDisplaySize(screenNumber, wParam, lParam); + break; + + case WMU_SET_BUFFER_FORMAT: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + masterIni->SetBufferFormat(screenNumber, wParam, (RDisplayChannel::TPixelFormat) lParam); + break; + + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + } + + +LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd) + { + TInt screenNumber = ScreenFromHWND(hWnd,TheChildWin); + if (TUint(screenNumber) >= TUint(masterIni->iBufferSet.Count())) + { + return EFalse; + } + + LPVOID displayBuffer = masterIni->iBufferSet[screenNumber].iDisplayBuffer; + if (!displayBuffer) + { + return EFalse; + } + + TInt frameOffset = masterIni->iBufferSet[screenNumber].iScreenBuffer.iDisplayBufferOffset; + displayBuffer=LPVOID(frameOffset+(char*)displayBuffer); + + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + + // Paint directly from the buffer to the window + LPBITMAPINFO info = (LPBITMAPINFO)&masterIni->iBufferSet[screenNumber].iInfo; + WORD width = (WORD)info->bmiHeader.biWidth; + WORD height = (WORD)-info->bmiHeader.biHeight; // stored -ve in info + SetDIBitsToDevice(ps.hdc, + 0, 0, // Dst X, Y + width, height, // Src W, H + 0, 0, // Src X, Y + 0, // Src offset to first line + height, // Src lines available + displayBuffer, // Src pointer to pixels + info, // Src info + DIB_RGB_COLORS); + + EndPaint(hWnd, &ps); + + return TRUE; + } + + +LOCAL_C void CalcTextPos(TInt aScreen, TInt& aX, TInt& aY) + { + switch (CurrentFlipState[aScreen]) + { + case EEmulatorFlipInvert: + aX = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth); + aY = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight); + break; + case EEmulatorFlipLeft: + aX = systemIni->iScreens[aScreen]->iScreenOffsetY; + aY = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth); + break; + case EEmulatorFlipRight: + aX = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight); + aY = systemIni->iScreens[aScreen]->iScreenOffsetX; + break; + case EEmulatorFlipRestore: + default: + aX = systemIni->iScreens[aScreen]->iScreenOffsetX; + aY = systemIni->iScreens[aScreen]->iScreenOffsetY; + break; + } + //subtract viewport offset here + aX -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetX(); + aY -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetY(); + } + +TInt APIENTRY ctrlwinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The control window function +// + { + switch(message) + { + case WM_SYSCOMMAND: + { + switch(wParam) + { + case 1: + { + NextConfiguration(); + return 0; + } + case SC_MINIMIZE: + case SC_RESTORE: + { + if (wParam == SC_RESTORE) + Active(); + for(TInt ix=0;ixiScreens.Count();ix++) + { + SendMessage(TheWin[ix],message,wParam,lParam); + } + if (wParam == SC_MINIMIZE) + Inactive(); + } + } + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + case WM_CLOSE: // tell all emulator screen windows to close + { + for(TInt i=0;iiScreens.Count();i++) + { + DestroyWindow(TheWin[i]); + } + DestroyWindow(hWnd); + break; + } + case WM_DESTROY: + { + // save the main window position information + HANDLE hSysIni; + hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + DScreenProperties* screenProps; + if (hSysIni != INVALID_HANDLE_VALUE) + { + DWORD numWritten; + //write an identifier into file so that program can avoid loading old version + WriteFile(hSysIni, &KDatFileVersion, sizeof(TInt), &numWritten, 0); + + //record current configuration at start of file. + WriteFile(hSysIni, &CurrentConfiguration, sizeof(TInt), &numWritten, 0); + + //Write out the state for each window. + for(TInt i=0;iiScreens.Count();i++) + { + screenProps= systemIni->iScreens[i]; + + TWindowState winState= screenProps->GetWindowState(); + WriteFile(hSysIni, &winState, sizeof(TWindowState), &numWritten, 0); + + + } + } + CloseHandle(hSysIni); + + PostQuitMessage(KErrNone); + break; + } + case WM_INPUT: + { + if (!DMultiTouch::iMultiTouchTempEnabled) + { + for(TInt ix=0;ixiScreens.Count();ix++) + { + DMultiTouch::iMultiTouchTempEnabled = TRUE; + + SendMessage(TheWin[ix],message,wParam,lParam); + } + } + else if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled()) + { + TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[0]); + } + else + { + Fault(EGuiInvalidMultiTouch); + } + break; + } + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + } + +TInt APIENTRY winProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The border window function. +// + { + + TRawEvent v; + + switch (message) + { + case WM_GETMINMAXINFO: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + + MINMAXINFO* minMaxInfo = reinterpret_cast(lParam); + minMaxInfo->ptMaxTrackSize.x = screenProps->iViewport.GetMaxWindowWidth(); + minMaxInfo->ptMaxTrackSize.y = screenProps->iViewport.GetMaxWindowHeight(); + + minMaxInfo->ptMaxSize.x = minMaxInfo->ptMaxTrackSize.x; + minMaxInfo->ptMaxSize.y = minMaxInfo->ptMaxTrackSize.y; + DefWindowProcA(hWnd, message, wParam, lParam); + + break; + } + + + + case WM_SIZE: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + //update size of viewport + viewport.SetViewportWidth(LOWORD(lParam)); + viewport.SetViewportHeight(HIWORD(lParam)); + + + //If resize goes beyond boundary of emulator then scroll to compensate + TInt ox = viewport.GetViewportOffsetX(); + TInt xs = ox + LOWORD(lParam) - viewport.GetMaxWidth(); + if (xs>0) + { + viewport.ScrollToX(ox-xs, hWnd); + } + + TInt oy = viewport.GetViewportOffsetY(); + TInt ys = oy + HIWORD(lParam) - viewport.GetMaxHeight(); + if (ys>0) + { + viewport.ScrollToY(oy-ys, hWnd); + } + + //Adjust ranges of scroll bars + viewport.UpdateScrollBarH(hWnd); + viewport.UpdateScrollBarV(hWnd); + + + + break; + } + case WM_HSCROLL: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + + switch (LOWORD(wParam)) + { + case SB_THUMBTRACK: + { + viewport.ScrollToX(HIWORD(wParam),hWnd); + break; + } + case SB_PAGELEFT: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() - viewport.GetViewportWidth(), hWnd ); + break; + } + case SB_PAGERIGHT: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() + viewport.GetViewportWidth() , hWnd); + break; + } + case SB_LINEUP: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() - 1, hWnd); + break; + } + case SB_LINEDOWN: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() + 1, hWnd); + break; + } + + } + + + break; + } + + case WM_VSCROLL: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + + + switch (LOWORD(wParam)) + { + case SB_THUMBTRACK: + { + viewport.ScrollToY(HIWORD(wParam), hWnd); + break; + } + case SB_PAGELEFT: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() - viewport.GetViewportHeight() , hWnd); + break; + } + case SB_PAGERIGHT: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() + viewport.GetViewportHeight(), hWnd ); + break; + } + case SB_LINEUP: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() - 1, hWnd); + break; + } + case SB_LINEDOWN: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() + 1, hWnd); + break; + } + + } + + break; + + } + + + case WM_FLIP_MESSAGE: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + + } + + TViewport& viewport = screenProps->iViewport; + RECT windowRect={0,0,0,0}; + GetClientRect(hWnd, &windowRect); + + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count())) + break; + PBITMAPV4HEADER info = &masterIni->iBufferSet[screenNumber].iInfo; + CurrentFlipState[screenNumber]=(TEmulatorFlip)wParam; + TBufferSet* bufferSet = &masterIni->iBufferSet[screenNumber]; + switch (CurrentFlipState[screenNumber]) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + windowRect.right=systemIni->iScreens[screenNumber]->iXYInputWidth; + windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputHeight; + info->bV4Width = bufferSet->iBufferFormat.iSize.iWidth; + info->bV4Height = -bufferSet->iBufferFormat.iSize.iHeight; + break; + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + windowRect.right=systemIni->iScreens[screenNumber]->iXYInputHeight; + windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputWidth; + info->bV4Width = bufferSet->iBufferFormat.iSize.iHeight; + info->bV4Height = -bufferSet->iBufferFormat.iSize.iWidth; + break; + } + AdjustWindowRect(&windowRect,KWinStyle,FALSE); + + + viewport.ScrollToX(0, hWnd); + viewport.ScrollToY(0, hWnd); + + + screenProps->iScreenRotation = (TEmulatorFlip)wParam; + + + RECT currentWindowRect; + GetWindowRect(hWnd,¤tWindowRect); + InvalidateRect(hWnd,NULL,FALSE); + MoveWindow( + TheWin[screenNumber], + max(currentWindowRect.left,0), // so the window doesn't disappear off the screen + max(currentWindowRect.top,0), + windowRect.right-windowRect.left, + windowRect.bottom-windowRect.top, + TRUE + ); + // move the child window + screenProps->iViewport.UpdateChildPos(hWnd); + + viewport.UpdateScrollBarH(hWnd); + viewport.UpdateScrollBarV(hWnd); + + InvalidateRect(hWnd,NULL,TRUE); + UpdateWindow(hWnd); + + break; + } + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + if (!(HIWORD(lParam)&KF_REPEAT)) + { + + + TUint scanCode=DWinsKeyboard::ScanCodeToStandardKey(HIWORD(lParam)); + TUint newScanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam)); + MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()}; + TranslateMessage(&msg); + TUint charCode=0; + // look in the message queue to get character associated with keypress + // so long as the control, shift and alt keys aren't depressed + if (!(HIBYTE(GetKeyState(VK_CONTROL)) && HIBYTE(GetKeyState(VK_MENU)) && HIBYTE(GetKeyState(VK_SHIFT)))) + if (PeekMessageA(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE) && + scanCode == newScanCode) //no remapping + charCode=msg.wParam; + // Pass the character as the HIWORD of the Epoc scan code + + scanCode = newScanCode; + v.Set(TRawEvent::EKeyDown,(charCode<<16)|scanCode); + if (!ProcessedByEmulatorKey(scanCode,hWnd,message,wParam,lParam)) + TheEventQ.Add(v); + + } + break; + case WM_TIMER: + break; + case WM_EMUL_POWER_ON: + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count())) + break; +// HWND win = systemIni->iSecureDisplay ? TheSecureChildWin : TheChildWin; + HWND win = TheChildWin[screenNumber]; + if (wParam==TRUE) + { + ShowWindow(win, SW_HIDE); + ShowWindow(win, SW_SHOWNORMAL); + if (SavedFlipMessage) + { + addKeyEvent(TRawEvent::EKeyDown, SavedFlipMessage); + addKeyEvent(TRawEvent::EKeyUp, SavedFlipMessage); + SavedFlipMessage = 0; + } + } + else + { + ShowWindow(win, SW_SHOWNORMAL); + ShowWindow(win, SW_HIDE); + } + } + break; + case WM_SYSKEYUP: + case WM_KEYUP: + { + //get the key code, this will pick up if it has been remapped or not. + TUint scanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam)); + /* + * We could do this to support generation of special characters using Alt+KeyPadNum + * combinations, but we would need to find a way to suppress the generation of + * home/end scancodes etc., so leave it for the moment. + MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()}; + TranslateMessage(&msg); + TUint charCode=0; + // look in the message queue to get character associated with keypress + if (PeekMessageU()(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE)) + charCode=msg.wParam; + // Pass the character as the HIWORD of the Epoc scan code + v.Set(TRawEvent::EKeyUp,(charCode<<16)|scanCode); + */ + v.Set(TRawEvent::EKeyUp,scanCode); + TheEventQ.Add(v); + break; + } + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + { + //only handle mouse clicks on screen 0 + TInt xpos=((TInt16)(lParam&0xffff)); + TInt ypos = (TInt16)((lParam>>16)&0xFFFF); + if (DMultiTouch::iMultiTouchTempEnabled) + { + MultiChildWndPointer(message,xpos,ypos,0,0); + DMultiTouch::iMultiTouchTempEnabled = FALSE; + } + else + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(screenNumber!=0) + break; + FrameWndPointer(message,xpos,ypos,screenNumber); + } + break; + } + case WM_PAINT: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + + PAINTSTRUCT p; + + BeginPaint(hWnd,&p); + HDC hdcBits; + BITMAP bm; + hdcBits=CreateCompatibleDC(p.hdc); + GetObjectA(TheScreenBitmap[screenNumber],sizeof(BITMAP),&bm); + SelectObject(hdcBits,TheScreenBitmap[screenNumber]); + + RECT windowRect; + GetClientRect(TheWin[screenNumber],&windowRect); + + viewport.SetViewportHeight(windowRect.bottom); + viewport.SetViewportWidth(windowRect.right); + + + switch (CurrentFlipState[screenNumber]) + { + case EEmulatorFlipRestore: + { + BitBlt(p.hdc,0,0,windowRect.right,windowRect.bottom,hdcBits, + viewport.GetViewportOffsetX(),viewport.GetViewportOffsetY(),SRCCOPY); + break; + } + case EEmulatorFlipInvert: + { + TInt sourceX = screenProps->iXYInputWidth - viewport.GetViewportWidth() - viewport.GetViewportOffsetX(); + if(sourceX<0) + sourceX=0; + TInt sourceY = screenProps->iXYInputHeight - viewport.GetViewportHeight() - viewport.GetViewportOffsetY(); + if(sourceY<0) + sourceY=0; + TInt sourceWidth = viewport.GetMaxWidth()-sourceX - viewport.GetViewportOffsetX(); + TInt sourceHeight = viewport.GetMaxHeight()-sourceY - viewport.GetViewportOffsetY(); + + //when inverted it is necessary to translate the image by 1 pixel up and to the left, + //to avoid a glitch when scrolling using ScrollWindowEx() + POINT arrayPoints[3]={ + {sourceWidth-1,sourceHeight-1}, + {-1,sourceHeight-1}, + {sourceWidth-1,-1} + }; + PlgBlt(p.hdc,arrayPoints,hdcBits,sourceX,sourceY,sourceWidth,sourceHeight,NULL,NULL,NULL); + break; + } + case EEmulatorFlipLeft: + { + TInt offsetX = screenProps->iXYInputWidth- viewport.GetViewportHeight() - viewport.GetViewportOffsetY(); + TInt offsetY = viewport.GetViewportOffsetX(); + + POINT arrayPoints[3]={{0,windowRect.bottom},{0,0},{windowRect.right,windowRect.bottom}}; + PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL); + break; + } + case EEmulatorFlipRight: + { + TInt offsetX = viewport.GetViewportOffsetY(); + TInt offsetY = screenProps->iXYInputHeight - viewport.GetViewportWidth() - viewport.GetViewportOffsetX(); + + POINT arrayPoints[3]={{windowRect.right,0},{windowRect.right,windowRect.bottom},{0,0}}; + PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL); + break; + } + } + + + DeleteDC(hdcBits); + if (WinsGuiPowerHandler->iStandby) + { + TInt x,y; + CalcTextPos(screenNumber, x, y); + TextOutA(p.hdc, x, y, "Standby", 7); + } + else if (systemIni->iScreens[screenNumber]->iScreenOff) + { + TInt x,y; + CalcTextPos(screenNumber, x, y); + TextOutA(p.hdc, x, y, "Screen Off", 10); + } + EndPaint(hWnd,&p); + break; + } + case WM_ACTIVATE: + //Added so that change in modifier keys can be detected without sending + //EActive/EInActive to wserv as it results in switching the timers + if((wParam & 0xffff)!= WA_INACTIVE) + UpdateModifiers(); + break; + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + break; + case WM_CLOSE: //pass on message to control window, it will then destroy all e,ulator windows + SendMessage(TheControlWin,WM_CLOSE, NULL, NULL); + break; + case WM_DESTROY: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + + // save window's position information + screenProps->iWinPlace.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hWnd, &screenProps->iWinPlace); + + break; + } + case WM_INPUT: + { + if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled()) + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(screenNumber==0) + { + TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[screenNumber]); + } + } + else + { + Fault(EGuiInvalidMultiTouch); + } + break; + } + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + + } + +void SetStatusBarFont(HWND& aStatusBar) + { + int statwidths[] = {100,200,300,400,500,600,700,800}; + SendMessage(aStatusBar, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths); + HFONT hOrigFont = (HFONT) SendMessage(aStatusBar, WM_GETFONT, 0, 0); + SetProp(aStatusBar, TEXT("PROP_ORIGINAL_FONT"), (HANDLE) hOrigFont); + LOGFONT lf; + GetObject(hOrigFont, sizeof(lf), &lf); + lf.lfHeight = (long)(lf.lfHeight / 1.5); + lf.lfWeight = FW_NORMAL; + HFONT hFont = CreateFontIndirect(&lf); + SetProp(aStatusBar, TEXT("PROP_ITALIC_FONT"), (HANDLE) hFont); + hFont = (HFONT) GetProp(hwndStatus, TEXT("PROP_ITALIC_FONT")); + SendMessage(aStatusBar, WM_SETFONT, (WPARAM) hFont, FALSE); + } + +DWORD WINAPI KernelWindowThread(LPVOID aArg) +// +// The kernel window thread. +// + { + HMODULE hmodule = GetModuleHandleA("winsgui.dll"); + __ASSERT_ALWAYS(hmodule!=NULL,Fault(EGuiGetModuleHandle)); + + WNDCLASSA w; + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC|CS_VREDRAW|CS_HREDRAW; + w.lpfnWndProc=(WNDPROC)ctrlwinProc; + w.hInstance=(HINSTANCE)aArg; + w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON)); + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszClassName="E32KernelControlWindow"; + + ATOM a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow)); + + RECT ctlrwindowRect={0,0,270,0}; + AdjustWindowRect(&ctlrwindowRect,KControlWinStyle,FALSE); + TInt ctrlwindowWidth=ctlrwindowRect.right-ctlrwindowRect.left; + TInt ctrlwindowHeight=ctlrwindowRect.bottom-ctlrwindowRect.top; + + TheControlWin=CreateWindowA( + "E32KernelControlWindow", + systemIni->iWindowTitle, + KInvisibleControlWinStyle, + KWinPosX, + KWinPosY, + ctrlwindowWidth, + ctrlwindowHeight, + (HWND)NULL, + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheControlWin!=NULL,Fault(EGuiKernelWindowCreate)); + + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC; + w.lpfnWndProc=(WNDPROC)winProc; + w.hInstance=(HINSTANCE)aArg; + w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON)); + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszClassName="E32KernelWindow"; + + a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow)); + + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC; + w.lpfnWndProc=(WNDPROC)childWinProc; + w.hInstance=(HINSTANCE)aArg; + w.hCursor=LoadCursorA(NULL,MAKEINTRESOURCEA(32512)); //ICD_ARROW + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszMenuName=NULL; + w.lpszClassName="E32KernelChildWindow"; + a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterChildWindow)); + + if (masterIni && masterIni->iSystemInis.Count() > 1) + { + //add Configuration Items to the system menu if there's > 1 config + HMENU hMenu = GetSystemMenu(TheControlWin, FALSE); + InsertMenu(hMenu,5, MF_BYPOSITION|MF_SEPARATOR,0,NULL); + InsertMenuA(hMenu,6, MF_BYPOSITION|MF_STRING, 1, "Next Config..."); + } + + ShowWindow(TheControlWin,SW_SHOWDEFAULT); + UpdateWindow(TheControlWin); + + //Create frame windows and child windows + for(TInt screen=0;screeniScreens.Count();screen++) + { + + RECT windowRect={0,0,systemIni->iScreens[screen]->iXYInputWidth,systemIni->iScreens[screen]->iXYInputHeight}; + AdjustWindowRect(&windowRect,KWinStyle,FALSE); + TInt windowWidth=windowRect.right-windowRect.left; + TInt windowHeight=windowRect.bottom-windowRect.top; + + CHAR title[20]; + wsprintfA(title, "Screen %d", screen); + + TheWin[screen]=CreateWindowA( + "E32KernelWindow", + title, + KInvisibleWinStyle, + KWinPosX, + KWinPosY, + windowWidth, + windowHeight, + (HWND)NULL, + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheWin[screen]!=NULL,Fault(EGuiKernelWindowCreate)); + + LoadFasciaBitmap(screen); + + TheChildWin[screen]=CreateWindowA( + "E32KernelChildWindow", + "", + WS_CHILDWINDOW|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, + systemIni->iScreens[screen]->iScreenOffsetX, + systemIni->iScreens[screen]->iScreenOffsetY, + systemIni->iScreens[screen]->iScreenWidth, + systemIni->iScreens[screen]->iScreenHeight, + TheWin[screen], + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheChildWin[screen]!=NULL,Fault(EGuiKernelChildWindowCreate)); + + // Create status bars + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled()) + { + HMODULE hmodComCtl = LoadLibrary(TEXT("comctl32.dll")); + typedef int (WINAPI* FNINITCC)(); + FNINITCC pfnInitCommonControls = GetProcAddress(hmodComCtl, "InitCommonControls"); + pfnInitCommonControls(); + hwndStatus = CreateWindowExA(0, STATUSCLASSNAMEA, NULL, + WS_CHILD | WS_VISIBLE | CCS_BOTTOM , + 0,0,0,0, + TheWin[0], NULL, GetModuleHandle(NULL), NULL); + SetStatusBarFont(hwndStatus); + SetWindowPos(hwndStatus,NULL, 0,0,0,0,SWP_HIDEWINDOW); + } + } + + //Restore window data from ini file if it exists. + HANDLE hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + TBool success=(hSysIni != INVALID_HANDLE_VALUE) ? ETrue : EFalse; + + DWORD numRead; + TInt fileVersion=0; + if(success) + { + ReadFile(hSysIni, &fileVersion, sizeof(TInt), &numRead, 0); + } + + //Check we are using a dat file created by this version of the program. + if(success && (fileVersion==KDatFileVersion) ) + { + + TInt savedConfiguration=0; //set this to default configuration + + if(ReadFile(hSysIni, &savedConfiguration, sizeof(TInt), &numRead, 0) && (numRead>0) ) + { + //Don't restore the saved configuration, see INC114502. + //This could be reenabled in future as an optional operation + //dependent on an entry in the epoc.ini file. + + //SwitchConfiguration(savedConfiguration); + } + + //restore each window to saved state + for(TInt screen=0;screeniScreens.Count();screen++) + { + + // If the .ini file was opened, get the saved settings for the windows position the last time + // this emulator was run, if any, and move the window accordingly. + + TWindowState savedState; + + TBool stateLoaded = ReadFile(hSysIni, &savedState, sizeof(TWindowState), &numRead, 0) && (numRead>0); + + if (stateLoaded) + { + //only allow window to be restored to + //maximized or normal mode, + //this prevents it being restored in minimized mode + //or others. + if(savedState.iWinPlace.showCmd != SW_MAXIMIZE) + savedState.iWinPlace.showCmd= SW_NORMAL; + + //if starting in same configuration and/or rotation as last time emulator was run + //it makes sense to restore scroll offset, window position, + //and dimensions, if not, only restore position and window (ie. maximized/normal) state. + if(savedConfiguration == CurrentConfiguration && + savedState.iFlipstate == CurrentFlipState[screen]) + { + //Restore window placement + SetWindowPlacement(TheWin[screen], &savedState.iWinPlace); + + TViewport& viewport = systemIni->iScreens[screen]->iViewport; + + viewport.ScrollToX(savedState.iXoffset, TheWin[screen]); + viewport.ScrollToY(savedState.iYoffset, TheWin[screen]); + } + else + { + + RECT oldRect; + GetWindowRect(TheWin[screen], &oldRect); + //save default window dimensions + TInt width=oldRect.right-oldRect.left; + TInt height=oldRect.bottom - oldRect.top; + + //restore position and window state from file + SetWindowPlacement(TheWin[screen], &savedState.iWinPlace); + + RECT currentRect; + GetWindowRect(TheWin[screen], ¤tRect); + //keep default size. + MoveWindow(TheWin[screen],currentRect.left, currentRect.top, width, height, TRUE); + + } + + + // Check that enough of the recorded window position is visible on the screen + + TBool enoughVisible = false; + + // vague values for ensuring we have enough of the window title bar to grab + // if the window is partly off screen + const TInt KTitleBarGrabX=80; + const TInt KTitleBarGrabY=50; + + //inspect dimensions of the window to be restored. + RECT savedRect; + GetWindowRect(TheWin[screen], &savedRect); + + SystemMonitors monitors; + + if (monitors.Count() == 1) /* Original algorithm */ + { + RECT rcIntersect, rcScreen; + + SetRect(&rcScreen, KTitleBarGrabX, savedRect.bottom-savedRect.top, + GetSystemMetrics(SM_CXSCREEN)-KTitleBarGrabX, GetSystemMetrics(SM_CYSCREEN)-KTitleBarGrabY); + + enoughVisible = IntersectRect(&rcIntersect, &savedRect, &rcScreen); + } + else /* > 1 monitor; do it differently */ + { + RECT cornerBox1, cornerBox2; + + // The top-left corner box + SetRect(&cornerBox1, savedRect.left, savedRect.top, + savedRect.left + KTitleBarGrabX, savedRect.top + KTitleBarGrabY); + + // The top-right corner box + SetRect(&cornerBox2, savedRect.right - KTitleBarGrabX, savedRect.top, + savedRect.right, savedRect.top + KTitleBarGrabY); + + // Require one of these rectangles to be all on one monitor + enoughVisible = monitors.RectAllOnOne(cornerBox1) || monitors.RectAllOnOne(cornerBox2); + } + + if (!enoughVisible) + { + SetWindowPos(TheWin[screen], HWND_TOP, 0,0,0,0, SWP_NOSIZE); + } + + } + else //if there was no stored info for this screen + { + ShowWindow(TheWin[screen],SW_MAXIMIZE); + } + } + } + else + { + //use default configuration and make windows visible + SwitchConfiguration(CurrentConfiguration); + for(TInt screen=0;screeniScreens.Count();screen++) + { + ShowWindow(TheWin[screen],SW_MAXIMIZE); + UpdateWindow(TheWin[screen]); + } + } + + //close file if it was opened + if(success) + { + CloseHandle(hSysIni); + } + + + if (systemIni->iInitialFlipMsg != 0) + { + addKeyEvent(TRawEvent::EKeyDown,systemIni->iInitialFlipMsg); + addKeyEvent(TRawEvent::EKeyUp,systemIni->iInitialFlipMsg); + } + + SetFocus(TheWin[0]); + + MSG m; + while (GetMessageA(&m,NULL,0,0)) + { + DispatchMessageA(&m); + } + + ExitProcess(m.wParam); + return 0; + } + +SystemMonitors::SystemMonitors(void) + { + TInt n; + + iCount = 1; + iHaveMultiMonFunctions = false; + + if ((n = GetSystemMetrics(SM_CMONITORS)) <= 1) + { + return; + } + + HMODULE huser32 = GetModuleHandleA("user32.dll"); + + // Get pointers to the APIs we want + if (huser32 == NULL || + (ipMonitorFromRect = + (HMONITOR (WINAPI *)(LPCRECT lprcScreenCoords, UINT uFlags)) + GetProcAddress(huser32, "MonitorFromRect")) == NULL || + (ipGetMonitorInfo = + (BOOL (WINAPI *)(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)) + GetProcAddress(huser32, "GetMonitorInfoA")) == NULL) + { + return; + } + + iCount = n; + iHaveMultiMonFunctions = true; + } + +TBool SystemMonitors::RectAllOnOne(RECT& rect) + { + HMONITOR monitor = MonitorFromRect(rect); + if (monitor == NULL) + { + return false; + } + + MONITORINFO monInfo; + monInfo.cbSize = sizeof(MONITORINFO); + + if (! GetMonitorInfo(monitor, &monInfo)) + { + return false; + } + + RECT overlap; + + if (IntersectRect(&overlap, &rect, &monInfo.rcWork) && + EqualRect(&overlap, &rect)) + { + return true; + } + + return false; + } + +HMONITOR SystemMonitors::MonitorFromRect(const RECT& rect, UINT flags) + { + if (! iHaveMultiMonFunctions) + { + return NULL; + } + + return (*ipMonitorFromRect)(&rect, flags); + } + +TBool SystemMonitors::GetMonitorInfo(HMONITOR monitor, LPMONITORINFO pMonInfo) + { + if (! iHaveMultiMonFunctions) + { + return false; + } + + return (*ipGetMonitorInfo)(monitor, pMonInfo); + } + +void DrawLeds() + { + HDC winDC = GetDC(TheWin[0]); + HDC hdcBits; + hdcBits=CreateCompatibleDC(winDC); + SelectObject(hdcBits,TheScreenBitmap[0]); + HPEN pen=CreatePen(PS_SOLID,0,RGB(0,0,0)); + SelectObject(hdcBits,pen); + HBRUSH brush; + LOGBRUSH redbrush={BS_SOLID, RGB(0xff,0,0)}; + LOGBRUSH greenbrush={BS_SOLID, RGB(0,0xff,0)}; + LOGBRUSH blackbrush={BS_SOLID, RGB(0,0,0)}; + // red + if (LedMask & KLedMaskRed1) + brush=CreateBrushIndirect(&redbrush); + else + brush=CreateBrushIndirect(&blackbrush); + SelectObject(hdcBits,brush); + DWinsUi *ini=systemIni; + Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY, ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize); + DeleteObject(brush); + // green + if (LedMask & KLedMaskGreen1) + brush=CreateBrushIndirect(&greenbrush); + else + brush=CreateBrushIndirect(&blackbrush); + SelectObject(hdcBits,brush); + if (ini->iLedVertical) + Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap, + ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize); + else + Ellipse(hdcBits, ini->iLedOffsetX+ini->iLedSize+ini->iLedGap, ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize); + DeleteObject(brush); + DeleteObject(pen); + DeleteDC(hdcBits); + ReleaseDC(TheWin[0], winDC); + if (ini->iLedVertical) + { + RECT r={ini->iLedOffsetX, + ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize, + ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize}; + InvalidateRect(TheWin[0], &r, FALSE); + } + else + { + RECT r={ini->iLedOffsetX, + ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize, + ini->iLedOffsetY+ini->iLedSize}; + InvalidateRect(TheWin[0], &r, FALSE); + } + } + +void DWinsUi::ScreenInfo(TScreenInfoV01& aInfo) +// +// Return screen 0 info to the window server. +// + { + aInfo.iWindowHandleValid=ETrue; + aInfo.iWindowHandle=TheChildWin[0]; + aInfo.iScreenAddressValid=EFalse; + aInfo.iScreenAddress=NULL; + aInfo.iScreenSize.iWidth = iScreens[0]->iMaxScreenWidth; + aInfo.iScreenSize.iHeight = iScreens[0]->iMaxScreenHeight; + } + + +TBool DWinsUi::VideoInfo(TInt aScreenNumber, TVideoInfoV01& aInfo) + { + return VideoInfo(aScreenNumber,iScreens[aScreenNumber&KMaskScreenNum]->iCurrentMode,aInfo); + } + +/// Could fail if flip mode is not supported +TBool DWinsUi::VideoInfo(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo) + { + aScreenNumber &= KMaskScreenNum; + if (aScreenNumber>=iScreens.Count()) + return EFalse; + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aScreenNumber].iDisplayDriverCount > 0) + { + return VideoInfoForDisplayDriver(aScreenNumber,aModeNumber,aInfo); + } + else + { + if ((aModeNumber&KMaskModeNum)>=1) + return EFalse; //non-gce emulator doesn't support changing the mode number. + DScreenProperties* screenProperties=iScreens[aScreenNumber]; + aInfo.iSizeInPixels.iWidth = screenProperties->iMaxScreenWidth; + aInfo.iSizeInPixels.iHeight = screenProperties->iMaxScreenHeight; + aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ? screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + aInfo.iIsMono = EFalse; + aInfo.iIsPalettized = EFalse; + aInfo.iDisplayMode=screenProperties->iCurrentMode; + aInfo.iIsPixelOrderRGB = ETrue; + aInfo.iIsPixelOrderLandscape=ETrue; + + aInfo.iVideoAddress = (TInt)TheChildWin[aScreenNumber]; + aInfo.iBitsPerPixel = screenProperties->iColorDepth; + aInfo.iOffsetToFirstPixel=0; + aInfo.iOffsetBetweenLines=0; + } + return ETrue; + } + +/** Could fail if flip mode is not supported. + Note that this method is inteneded to be called directly to parameterise the setting up of the display driver, + so it must survive absense of the display driver installation! +**/ + +TBool DWinsUi::VideoInfoForDisplayDriver(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo, TBool aRealWidthAndHeight) + { + aScreenNumber &= KMaskScreenNum; + DScreenProperties* screenProperties = iScreens[aScreenNumber]; + if ((aModeNumber&KMaskModeNum) >= screenProperties->iMaxModes) + { + return EFalse; + } + + aInfo.iSizeInPixels.iWidth = aRealWidthAndHeight ? screenProperties->iScreenWidth : screenProperties->iMaxScreenWidth; + aInfo.iSizeInPixels.iHeight = aRealWidthAndHeight ? screenProperties->iScreenHeight : screenProperties->iMaxScreenHeight; + + if (aRealWidthAndHeight==EFalse) + { + aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ? screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + } + else + { + aInfo.iSizeInTwips.iWidth = screenProperties->iPhysicalScreenWidth ? screenProperties->iPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iPhysicalScreenHeight ? screenProperties->iPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + } + + aInfo.iIsMono = EFalse; + aInfo.iIsPalettized = EFalse; + aInfo.iDisplayMode=screenProperties->iCurrentMode; + aInfo.iIsPixelOrderRGB = ETrue; + aInfo.iIsPixelOrderLandscape=ETrue; + + // Set memory to iVideoAddress to NULL to trigger the HAL code into querying the video address + // separately + aInfo.iVideoAddress = NULL; + + TInt bpp=screenProperties->iModeDepths[aModeNumber&KMaskModeNum]; + aInfo.iBitsPerPixel=bpp; + if (bpp>8) + { + bpp=(bpp+15)&-16; //12 & 16 --> 16 ; 24 & 32 --> 32 + } + + aInfo.iOffsetToFirstPixel=0; +#ifdef TEST_GCE_VARIABLE_START_EXTRA + aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*(1+aModeNumber&KMaskScreenModeNum); + if ((aModeNumber& KModeFlagFlipped) + { +#ifndef ASSYMETRIC_SQUARE_STRIDE + if (aInfo.iSizeInPixels.iWidth!=aInfo.iSizeInPixels.iHeight) +#endif + aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*KEmulMaxNumModes; + } +#endif + if (aModeNumber& KModeFlagFlipped) + { + // we calculate the number of bytes per scanline that MUST be a multiple of 32 bits word (alignment) + // screenProperties->iMaxScreenHeight * bpp represnts the number of bits per scanline + // +31 is the ceiling + // we shift right (>>3) because there are 8 bits/byte + // we mask with ~3 because we are intrested in the octet value + aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenHeight * bpp + 31) >> 3) & ~3; + } + else + { + // please see the comment above + aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenWidth * bpp + 31) >> 3) & ~3; + } +#ifdef TEST_GCE_VARIABLE_STRIDE_EXTRA + aInfo.iOffsetBetweenLines+=TEST_GCE_VARIABLE_STRIDE_EXTRA; +#endif + + return ETrue; + } + +TInt DMasterIni::DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) + { + return masterIni->HalFunction((TInt)aPtr,aFunction,a1,a2); + } + + +TInt DMasterIni::HalFunction(TInt aDeviceNumber, TInt aFunction, TAny* a1, TAny* a2) + { + if (TUint(aDeviceNumber) >= TUint(systemIni->iScreens.Count())) + return KErrArgument; + + TInt mode; + TInt maxMode=1; + TInt r=KErrNone; + switch(aFunction) + { + case EDisplayHalScreenInfo: + { + TPckgBuf vPckg; + systemIni->ScreenInfo(vPckg()); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + break; + } + case EDisplayHalWsRegisterSwitchOnScreenHandling: + WsSwitchOnScreen=(TBool)a1; + break; + case EDisplayHalSetState: + { + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState"))) + return KErrPermissionDenied; + if ((TBool)a1) + WinsGuiPowerHandler->ScreenOn(aDeviceNumber); + else + WinsGuiPowerHandler->ScreenOff(aDeviceNumber); + } + break; + + case EDisplayHalState: + *(TInt*)a1=!systemIni->iScreens[aDeviceNumber]->iScreenOff; + break; + case EDisplayHalWsSwitchOnScreen: + WinsGuiPowerHandler->ScreenOn(); + break; + case EDisplayHalMaxDisplayContrast: + kumemput32(a1,&KMaxDisplayContrast,sizeof(KMaxDisplayContrast)); + break; + case EDisplayHalDisplayContrast: + kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iDisplayContrast,sizeof(systemIni->iScreens[aDeviceNumber]->iDisplayContrast)); + break; + case EDisplayHalSetDisplayContrast: + if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayContrast"))) + return KErrPermissionDenied; + if (TUint(a1) <= TUint(KMaxDisplayContrast)) + systemIni->iScreens[aDeviceNumber]->iDisplayContrast = TInt(a1); + else + r = KErrArgument; + break; + case EDisplayHalBacklightOn: + { + TBool c = EFalse; + kumemput32(a1,&c,sizeof(TBool)); + } + break; + + case EDisplayHalCurrentModeInfo: + { + //a1 has ptr to buffer for results + TPckgBuf vPckg; + if (systemIni->VideoInfo(aDeviceNumber, vPckg())) + Kern::InfoCopy(*(TDes8*)a1,vPckg); + else + r=KErrNotSupported; + } + break; + + case EDisplayHalSpecifiedModeInfo: + { + kumemget32(&mode, a1, sizeof(mode)); + TPckgBuf vPckg; + if (!systemIni->VideoInfo(aDeviceNumber, mode, vPckg())) + return KErrArgument; + Kern::InfoCopy(*(TDes8*)a2, vPckg); + } + break; + + case EDisplayHalSetMode: +// if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode"))) +// return KErrPermissionDenied; + + //Note that at present the HAL mode does not apparently get set when the CFbsScreenDevice requires a different mode. + //At least in the emulator and default h4 implementation... + + mode=KMaskModeNum&(TInt) a1; + maxMode=1; + //can't avoid this behaviour change test against gce loaded + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0) + maxMode=systemIni->iScreens[aDeviceNumber]->iMaxModes; + if (mode >=maxMode || mode<0) + { + r = KErrArgument; + break; + } + //Harmless/Pointless in vanilla wins mode. + systemIni->iScreens[aDeviceNumber]->iCurrentMode=mode; + + break; + + case EDisplayHalMode: + { + //This is always 0 in non-gce emulator + kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iCurrentMode,sizeof(systemIni->iScreens[aDeviceNumber]->iCurrentMode)); + } + break; + + case EDisplayHalModeCount: + { + //Need to actually count them here! + //GCE will ignore modes<=8 + TInt encodedMode=1; + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0) + encodedMode=systemIni->iScreens[aDeviceNumber]->iMaxModes; + kumemput32(a1,&encodedMode,sizeof(encodedMode)); + } + break; + + case EDisplayHalColors: + { + TInt deepestMode=0; + if (masterIni->iBufferSet.Count()==0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0) + { + deepestMode = KMaxDisplayColors; //I could try and work it out, but this is what used to happen! + } + else + { + TInt maxBpp=0; + for (TInt i=0,maxI=systemIni->iScreens[aDeviceNumber]->iMaxModes;iiScreens[aDeviceNumber]->iModeDepths[i]>maxBpp) + maxBpp=systemIni->iScreens[aDeviceNumber]->iModeDepths[i]; + deepestMode= 1<iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 )) + { + r = masterIni->DisplayMemoryHandle(aDeviceNumber, val); + } + else + { + r = KErrArgument; + } + NKern::ThreadLeaveCS(); + } + kumemput32(a1, &val, sizeof(TInt)); + + } + break; + + case EDisplayHalGetDisplayMemoryAddress: + { + TInt val = 0; + TInt passedIn = 0; + kumemget32(&passedIn, a1, sizeof(TInt)); + if (passedIn != -1) //not from a getall + { + if (!(masterIni->iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 )) + { + r = masterIni->DisplayMemoryAddress(aDeviceNumber, val); + } + else + { + r = KErrArgument; + } + } + kumemput32(a1, &val, sizeof(TInt)); + } + break; + + case EDisplayHalNumberOfResolutions: + { + r = NumberOfResolutions(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalSpecificScreenInfo: + { + r = SpecificScreenInfo(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalCurrentScreenInfo: + { + r = CurrentScreenInfo(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalSetDisplayState: + { + //increase the spinner at both beginning and end of resetting the display state + NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount); + kumemget32(&iBufferSet[aDeviceNumber].iDisplayState, a1, sizeof(TInt)); + + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: + case EDisconnect: + case ESingleResolution: + // the fascia effect of 0x0 resolution + SetDisplaySize(aDeviceNumber, 0, 0); + break; + } + + NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount); + } + break; + case EDisplayHalGetStateSpinner: + { + kumemput32(a1,&iBufferSet[aDeviceNumber].iStateChangeCount, + sizeof(iBufferSet[aDeviceNumber].iStateChangeCount)); + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::NumberOfResolutions(TInt aDeviceNumber, TAny* a1, TAny* a2) + { + TInt numberOfConfigs; + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: + { + numberOfConfigs = 0; + } + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: + { + numberOfConfigs = 1; + } + break; + case ENormalResolution: + default: + { + numberOfConfigs = iSystemInis.Count(); + if (numberOfConfigs > 1) + { + TVideoInfoV01 info1; + TVideoInfoV01 info2; + iSystemInis[0]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info1, ETrue); + iSystemInis[1]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info2, ETrue); + if (info1.iSizeInPixels.iWidth == info2.iSizeInPixels.iWidth && + info1.iSizeInPixels.iHeight == info2.iSizeInPixels.iHeight) + { + numberOfConfigs = 1; //It looks like all resolutions for this device are the same + } + } + } + } + kumemput32(a1,&numberOfConfigs,sizeof(numberOfConfigs)); + if(a2) + { + kumemput32(a2,&(iBufferSet[aDeviceNumber].iStateChangeCount),sizeof(iBufferSet[aDeviceNumber].iStateChangeCount)); + } + return KErrNone; + } + +TInt DMasterIni::SpecificScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* a2) + { + TInt config; + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: //Do Nothing + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: //fill (0,0) as the only element in resolution array + { + if(*(TInt*)a1 == 0) + { + TVideoInfoV01 info; + info.iSizeInPixels.iHeight = 0; + info.iSizeInPixels.iWidth = 0; + info.iSizeInTwips.iHeight = 0; + info.iSizeInTwips.iWidth = 0; + TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info)); + Kern::InfoCopy(*(TDes8*)a2, infoPtr); + } + } + break; + case ENormalResolution: + default: + { + kumemget32(&config, a1, sizeof(config)); + TPckgBuf vPckg; + iSystemInis[config]->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue); + Kern::InfoCopy(*(TDes8*)a2,vPckg); + } + } + return KErrNone; + } + +TInt DMasterIni::CurrentScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* /*a2*/) + { + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: //Do Nothing + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: //fill (0,0) + { + TVideoInfoV01 info; + info.iSizeInPixels.iHeight = 0; + info.iSizeInPixels.iWidth = 0; + info.iSizeInTwips.iHeight = 0; + info.iSizeInTwips.iWidth = 0; + TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info)); + Kern::InfoCopy(*(TDes8*)a1, infoPtr); + } + break; + case ENormalResolution: + default: + { + TPckgBuf vPckg; + systemIni->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + } + return KErrNone; + } + +TInt DMasterIni::DoXYHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2) + { + return static_cast(aThis)->XYHalFunction(aFunction,a1,a2); + } + +TInt DMasterIni::XYHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/) + { + TInt r=KErrNone; + switch(aFunction) + { + case EDigitiserHalXYInfo: + { + if(systemIni->iXYInputType==EXYInputPointer) + { + TPckgBuf vPckg; + TDigitiserInfoV01& xyinfo=vPckg(); + xyinfo.iDigitiserSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX); + xyinfo.iDigitiserSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY); + xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX; + xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY; + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + else + r=KErrNotSupported; + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::DoMouseHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2) + { + return static_cast(aThis)->MouseHalFunction(aFunction,a1,a2); + } + +TInt DMasterIni::MouseHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/) + { + TInt r=KErrNone; + switch(aFunction) + { + case EMouseHalMouseInfo: + { + if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse) + { + TPckgBuf vPckg; + TMouseInfoV01& xyinfo=vPckg(); + xyinfo.iMouseButtons=2; + xyinfo.iMouseAreaSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX); + xyinfo.iMouseAreaSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY); + xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX; + xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY; + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + else + r=KErrNotSupported; + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::DoKbdHalFunction(TAny* /*aThis*/, TInt aFunction, TAny* /*a1*/, TAny* /*a2*/) + { + // don't actually do anything, just enough to report a Keyboard is present + TInt r=KErrNone; + if(aFunction!=EKeyboardHalKeyboardInfo) + r=KErrNotSupported; + return r; + } + +void Inactive() +// +// Window has been minimised. +// + { + + TRawEvent v; + v.Set(TRawEvent::EInactive); + TheEventQ.Add(v); + } + +void UpdateModifiers() +//Updates the modifier key states and sends an event to wserv about the +//change in state + { + TRawEvent v; + TInt modifiers=0; + if(GetKeyState(VK_SCROLL)&1) + modifiers|=EModifierScrollLock; + if(GetKeyState(VK_NUMLOCK)&1) + modifiers|=EModifierNumLock; + if(GetKeyState(VK_CAPITAL)&1) + modifiers|=EModifierCapsLock; + v.Set(TRawEvent::EUpdateModifiers,modifiers); + TheEventQ.Add(v); + } + +void Active() +// +// Window has been restored. +// Update the toggling modifiers, reset any others +// + { + TRawEvent v; + UpdateModifiers(); + v.Set(TRawEvent::EActive); + TheEventQ.Add(v); + } + + +void ClearScreen() + { + + } + + +TInt DWinsUi::GetVirtualKey(TEmulCommand& aCommand, TInt aX, TInt aY) + { + //if the point is in the list of shapes, set the key and return true + for (TInt keyCount = iVirtualKeys.Count(); --keyCount >= 0; ) + { + const VirtualKey& vk = *iVirtualKeys[keyCount]; + if (vk.Contains(aX, aY)) + { + aCommand = vk.Command(); + return vk.Value(); + } + } + return -1; + } + +void DWinsUi::TranslateMouseCoords(const TEmulatorFlip aFlipState, const TInt aX, const TInt aY, const TInt aRegionWidth, const TInt aRegionHeight, TInt& aNewX, TInt& aNewY) + { + switch (aFlipState) + { + case EEmulatorFlipRestore: + aNewX = aX; + aNewY = aY; + break; + + case EEmulatorFlipInvert: + aNewX = aRegionWidth - aX; + aNewY = aRegionHeight - aY; + break; + + case EEmulatorFlipLeft: + aNewX = aRegionWidth - aY; + aNewY = aX; + break; + + case EEmulatorFlipRight: + aNewX = aY; + aNewY = aRegionHeight - aX; + break; + } + } + + +TBool DWinsUi::OnScreen(TInt aScreen, TInt ax, TInt ay) const +// +// Checks if a point within the Emulator window is on the screen +// + { + return (TUint(ax) < TUint(systemIni->iScreens[aScreen]->iScreenWidth) && TUint(ay) < TUint(systemIni->iScreens[aScreen]->iScreenHeight)); + } + +TInt DWinsUi::Create(TInt aId) + { + TInt r = SetupProperties(aId); + if (r != KErrNone) + return r; + TInt screen; + DScreenProperties* currentScreen = NULL; + for(screen=0;screeniFasciaFileName) == KErrNone) + { + currentScreen->iXYInputWidth=bitmapinfo.biWidth; + currentScreen->iXYInputHeight=bitmapinfo.biHeight; + } + currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,currentScreen->iScreenWidth+currentScreen->iScreenOffsetX); + currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,currentScreen->iScreenHeight+currentScreen->iScreenOffsetY); + } + + currentScreen = iScreens[0]; + //note digitizer offsets are relative to EPOC screen 0 + if (-1 == iDigitizerWidth) + iDigitizerWidth = currentScreen->iXYInputWidth - + (currentScreen->iScreenOffsetX + iDigitizerOffsetX); + else + currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,iDigitizerWidth); + + if (-1 == iDigitizerHeight) + iDigitizerHeight = currentScreen->iXYInputHeight - + (currentScreen->iScreenOffsetY + iDigitizerOffsetY); + else + currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,iDigitizerHeight); + + return r; + } + +const RDisplayChannel::TPixelFormat DMasterIni::iSupportedPixelFormatTable[] = + { + EUidPixelFormatXRGB_8888, + EUidPixelFormatARGB_8888, + EUidPixelFormatARGB_8888_PRE, + EUidPixelFormatXRGB_4444, + EUidPixelFormatARGB_4444, + EUidPixelFormatRGB_565 + }; + +const TInt DMasterIni::iSupportedPixelFormatTableSize = static_cast(sizeof(iSupportedPixelFormatTable)/ + sizeof(iSupportedPixelFormatTable[0])); + +void DMasterIni::InitBufferFormat(DScreenProperties& aScreenProperties, RDisplayChannel::TBufferFormat& aBufferFormat) + { + TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth); + + aBufferFormat.iSize.iWidth = aScreenProperties.iMaxScreenWidth; + aBufferFormat.iSize.iHeight = aScreenProperties.iMaxScreenHeight; + switch (bitsPerPixel) + { + case 12: // XRGB4444 + aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_4444; + break; + case 16: // RGB565 + aBufferFormat.iPixelFormat = EUidPixelFormatRGB_565; + break; + case 24: // Really 32bpp, but top 8 unused + case 32: // While 32bpp, top 8 will not be used + default: + aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_8888; + break; + } + } + +TInt DMasterIni::Create() + { + TInt configurations = Property::GetInt("ConfigCount", 0); + if (configurations == 0) + return KErrGeneral; + + // the pixel formats table is, at present, configuration independent + TInt count; + TInt r = KErrNone; + for (count = 0; count < configurations && r == KErrNone; ++count) + { + DWinsUi* dwi = new DWinsUi; + if (dwi) + r = dwi->Create(count); + + if (r == KErrNone) + iSystemInis.Append(dwi); + } + if (r != KErrNone) + return r; + + systemIni = masterIni->iSystemInis[0]; + + WinsGuiPowerHandler = DWinsGuiPowerHandler::New(); + if (!WinsGuiPowerHandler) + return KErrNoMemory; + + TheWin=new HWND[systemIni->iScreens.Count()]; + TheChildWin=new HWND[systemIni->iScreens.Count()]; + TheScreenBitmap=new HBITMAP[systemIni->iScreens.Count()]; + CurrentFlipState=new TEmulatorFlip[systemIni->iScreens.Count()]; + + if(!TheWin || !TheChildWin || !TheScreenBitmap || !CurrentFlipState) + return KErrNoMemory; + memset(CurrentFlipState,EEmulatorFlipRestore,systemIni->iScreens.Count()); + + TBufferSet buffer; + buffer.iDisplayDriverCount = 0; + buffer.iDisplayState = ENormalResolution; + buffer.iDisplayBuffer = 0; + buffer.iDisplayChannel = NULL; + + + TInt i; + for(i=0;iiScreens.Count();i++) + { + DScreenProperties *pScr = systemIni->iScreens[i]; + + masterIni->InitBitmapHeader(*pScr, &buffer.iInfo); + masterIni->InitBufferFormat(*pScr, buffer.iBufferFormat); + + r = masterIni->iBufferSet.Append(buffer); + if (r != KErrNone) + return r; + } + + if (CreateWin32Thread(EThreadEvent, &KernelWindowThread, NULL, ETrue) == NULL) + return KErrGeneral; + + for(i=0;iiScreens.Count();i++) + { + r = Kern::AddHalEntry(EHalGroupDisplay,&DoHalFunction,(TAny*)i,i); + if (r != KErrNone) + return r; + } + + // should really come from Keyboard driver, but not doing it now... + r = Kern::AddHalEntry(EHalGroupKeyboard,&DoKbdHalFunction,this); + if (r != KErrNone) + return r; + + if(systemIni->iXYInputType==EXYInputPointer) + { + r = Kern::AddHalEntry(EHalGroupDigitiser,&DoXYHalFunction,this); + if (r != KErrNone) + return r; + } + else if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse) + { + r = Kern::AddHalEntry(EHalGroupMouse,&DoMouseHalFunction,this); + if (r != KErrNone) + return r; + } + + return r; + } + +void DMasterIni::InitBitmapHeader(DScreenProperties& aScreenProperties, LPBITMAPV4HEADER aInfo) + { + TInt width = aScreenProperties.iMaxScreenWidth; + TInt height = aScreenProperties.iMaxScreenHeight; + TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth); + + memset(aInfo, 0, sizeof(BITMAPV4HEADER)); + + switch (bitsPerPixel) + { + case 12: // XRGB4444 + aInfo->bV4BitCount = 16; + aInfo->bV4V4Compression = BI_BITFIELDS; + aInfo->bV4RedMask = 0x0F00; + aInfo->bV4GreenMask = 0x00F0; + aInfo->bV4BlueMask = 0x000F; + break; + case 16: // RGB565 + aInfo->bV4BitCount = 16; + aInfo->bV4V4Compression = BI_BITFIELDS; + aInfo->bV4RedMask = 0xF800; + aInfo->bV4GreenMask = 0x07E0; + aInfo->bV4BlueMask = 0x001F; + break; + case 24: // Really 32bpp, but top 8 unused + case 32: // While 32bpp, top 8 will not be used + default: + aInfo->bV4BitCount = 32; + aInfo->bV4V4Compression = BI_RGB; + // Mask is implicit for BI_RGB compression + break; + } + + aInfo->bV4Size = sizeof(BITMAPV4HEADER); + aInfo->bV4Width = width; + aInfo->bV4Height = -height; // Bitmap runs top to bottom + aInfo->bV4Planes = 1; + + TInt bpp = _ALIGN_UP(aInfo->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32 + TInt widthInPixel = aInfo->bV4Width * bpp; + //rounding to 32 bits (4 octets) and converting, then, bits to octets; + TInt scanLineInBytes = _ALIGN_UP(widthInPixel, 32) >> 3; + aInfo->bV4SizeImage = -aInfo->bV4Height * scanLineInBytes; + + // Set color space as uncalibrated. All other members are then ignored. +#if defined(LCS_DEVICE_RGB) + aInfo->bV4CSType = LCS_DEVICE_RGB; +#elif defined(LCS_sRGB) + aInfo->bV4CSType = LCS_sRGB; +#endif + } + +// Helper function that allocates a single frame buffer. +static TInt AllocateOneFrameBuffer(TInt aSize, TScreenBuffer &aScreenBuffer) + { + // Open shared chunk to the composition framebuffer + DChunk* chunk = 0; + // round to page size + if (aSize <= 0) + return KErrArgument; + TUint round = Kern::RoundToPageSize(aSize); + TLinAddr chunkKernelAddr = 0; + TUint32 physicalAddress = 0; + TUint32 chunkMapAttr = 0; + + // create shared chunk + NKern::ThreadEnterCS(); + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = round; + info.iMapAttr = 0; + info.iOwnsMemory = ETrue; + info.iDestroyedDfc = 0; + + TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); + if (r == KErrNone) + { + // map our chunk to specific + r = Kern::ChunkCommitContiguous(chunk, 0, aSize, physicalAddress); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + } + } + + if (r == KErrNone) + { + TBufferAddressA* bufferAddress = new TBufferAddressA; + if (!bufferAddress) + { + r = KErrNoMemory; + } + else + { + bufferAddress->iAddress = (TAny*)chunkKernelAddr; + bufferAddress->iChunk = chunk; + + if ((r = aScreenBuffer.iFrameBuffers.Append(bufferAddress->iAddress)) == KErrNone) + { + r = aScreenBuffer.iMemChunks.Append(bufferAddress); + } + } + } + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + } + NKern::ThreadLeaveCS(); + return KErrNone; + } + +TInt DMasterIni::AllocateFrameBuffers(TInt aScreenNumber, TInt aCount, TInt aSize) + { + while (aCount--) + { + TInt r = AllocateOneFrameBuffer(aSize, masterIni->iBufferSet[aScreenNumber].iScreenBuffer); + if (r != KErrNone) + { + return r; + } + } + return KErrNone; + } + +void DMasterIni::ReleaseFrameBuffers(TInt aScreenNumber) + { + RPointerArray& frameBuffers = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iFrameBuffers; + RPointerArray& memChunks = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iMemChunks; + RPointerArray& dsaChunks = masterIni->iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks; + + NKern::ThreadEnterCS(); + TInt index; + TInt count = memChunks.Count(); + for (index = 0; index < count; index++) + { + Kern::ChunkClose(memChunks[index]->iChunk); + } + count = dsaChunks.Count(); + for (index = 0; index < count; index++) + { + Kern::ChunkClose(dsaChunks[index]->iChunk); + } + NKern::ThreadLeaveCS(); + + frameBuffers.Reset(); + memChunks.Reset(); + dsaChunks.Reset(); + } + + +TProcessAddrEntry::TProcessAddrEntry(DProcess *aProcess, TUint8* aAddress): + iProcess(aProcess), iAddress(aAddress) + { + } + + +/** +Contruct a Shared Chunk cleanup object which will be used to clean up +after the process/address table entry. +*/ +TChunkCleanup::TChunkCleanup(DProcess* aProcess, TInt aScreenNumber) + : TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0) + , iProcess(aProcess) + , iScreenNumber(aScreenNumber) + , iIndex(-1) + {} + +/** +Cancel the action of the cleanup object. +*/ +void TChunkCleanup::Cancel() + { + // Clear iProcess which means that when the DFC gets queued on chunk destruction + // our ChunkDestroyed method will do nothing other than cleanup itself. + iProcess = NULL; + } + +/** +Callback function called when the DFC runs, i.e. when a chunk is destroyed. +*/ +void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf) + { + DProcess* process = aSelf->iProcess; + TInt screenNumber = aSelf->iScreenNumber; + TUint index = aSelf->iIndex; + // If we haven't been Cancelled... + if(process && index != -1) + { + if (masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess == process) + { + masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess = 0; + } + else + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Oops! Someone has messed up our process index!")); + } + } + + // We've finished so now delete ourself + delete aSelf; + } + + +TInt DMasterIni::DisplayMemoryHandle(TInt aScreenNumber, TInt& aHandle) + { + if (iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks.Count() == 0) + { + int r; + r = AllocateOneFrameBuffer(iMaxSizeInBytes, iBufferSet[aScreenNumber].iDsaBuffer); + if (KErrNone != r) + { + return r; + } + __ASSERT_DEBUG(iBufferSet[aScreenNumber].iDisplayChannel, Fault(EGuiNoDisplayChannel)); + iBufferSet[aScreenNumber].iDisplayChannel->SetLegacyBuffer(iBufferSet[aScreenNumber].iDsaBuffer.iFrameBuffers[0]); + } + + aHandle = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), + iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks[0]->iChunk); + + if (aHandle < 0) + { + return aHandle; + } + + return KErrNone; + } + + + +// Find the address of the display memory. +TInt DMasterIni::DisplayMemoryAddress(TInt aScreenNumber, TInt& aAddress) + { + TBufferSet &bufferSet = iBufferSet[aScreenNumber]; + DProcess *process = &Kern::CurrentProcess(); + TInt firstFree = -1; + NKern::FMWait(&iLock); + TUint count = bufferSet.iProcAddrTable.Count(); + for(TUint i = 0; i < count; ++i) + { + DProcess *curProcess = bufferSet.iProcAddrTable[i].iProcess; + if (curProcess == process) + { + aAddress = reinterpret_cast(bufferSet.iProcAddrTable[i].iAddress); + NKern::FMSignal(&iLock); + return KErrNone; + } + if (curProcess == 0 && firstFree == -1) + { + firstFree = i; + } + } + NKern::FMSignal(&iLock); + // If we get here, we couldn't find the process in the iProcAddrTable. + // Create a new Process Address entry. + // Step 1 + // Create a dummy chunk so that we can detect when the process dies, + // give a handle to the user [but don't actually let the process KNOW what the handle is + // so the user process can't do anything silly with the chunk]. Close our side of the + // chunk to make sure there is only one reference to it. + DChunk* chunk = 0; + // find page size for one page. + TUint round = Kern::RoundToPageSize(1); + TLinAddr chunkKernelAddr = 0; + TUint32 chunkMapAttr = 0; + + // create shared chunk + NKern::ThreadEnterCS(); + // Cleanup object, used to issue a DFC when the chunk is closed (and + // as the handle of the chunk is not given to the process, it can only + // be closed when the process terminates!) + TChunkCleanup *cleanup = new TChunkCleanup(process, aScreenNumber); + if (!cleanup) + { + NKern::ThreadLeaveCS(); + return KErrNoMemory; + } + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = round; + info.iMapAttr = 0; + info.iOwnsMemory = ETrue; + info.iDestroyedDfc = cleanup; + + TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); + + if (r != KErrNone) + { + delete cleanup; + NKern::ThreadLeaveCS(); + return r; + } + + + // Create a new handle for the user thread. + r = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), chunk); + Kern::ChunkClose(chunk); + if (r <= 0) + { + NKern::ThreadLeaveCS(); + return r; + } + + // Step 2 + // Create a second handle for the chunk to the DSA buffer. + // First part: Make sure there is a DisplayMemoryHandle; + TInt handle = 0; + r = DisplayMemoryHandle(aScreenNumber, handle); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return r; + } + + DChunk *dsaChunk = bufferSet.iDsaBuffer.iMemChunks[0]->iChunk; + + // Step 3 + // Get the base addrss and insert into table. + TUint8* baseAddress = Kern::ChunkUserBase(dsaChunk, &Kern::CurrentThread()); + NKern::FMWait(&iLock); + // Optimistically, the place we found earlier in the table is still free. + if (firstFree != -1 && bufferSet.iProcAddrTable[firstFree].iProcess != 0) + { + // If not, we go find another one. + firstFree = -1; + TUint count = bufferSet.iProcAddrTable.Count(); + for(TUint i = 0; i < count; ++i) + { + if (bufferSet.iProcAddrTable[i].iProcess == 0) + { + firstFree = i; + break; + } + } + } + // Check if there is a free entry - if so, re-use it. + if (firstFree != -1) + { + bufferSet.iProcAddrTable[firstFree].iProcess = process; + bufferSet.iProcAddrTable[firstFree].iAddress = baseAddress; + cleanup->SetIndex(firstFree); + NKern::FMSignal(&iLock); + } + else + { + // No free entry. Append it to the list. + NKern::FMSignal(&iLock); + TProcessAddrEntry entry(process, baseAddress); + r = bufferSet.iProcAddrTable.Append(entry); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return r; + } + // We added it at the end - so we start from the back and check for the + // process, as some other process COULD have added one after us, so we + // can't just use the count for index! + TUint index; + for(index = bufferSet.iProcAddrTable.Count()-1; index; --index) + { + if (bufferSet.iProcAddrTable[index].iProcess == process + && bufferSet.iProcAddrTable[index].iAddress != baseAddress) + { + break; + } + } + cleanup->SetIndex(index); + } + aAddress = reinterpret_cast(baseAddress); + + NKern::ThreadLeaveCS(); + return KErrNone; + } + +EXPORT_C TInt WinsGui::CurrentConfiguration() + { + return ::CurrentConfiguration; + } + +GLDEF_C void Fault(TGuiPanic aPanic) + { + Kern::Fault("WINS-UI",aPanic); + } + +DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting Emulator GUI")); + + // if NoGui property == true do nothing + if (Property::GetBool("NoGui",EFalse)) + return KErrNone; + + // create keyboard driver + TInt r=KErrNoMemory; + masterIni = new DMasterIni; + if (masterIni) + { + r = masterIni->Create(); + if (r!= KErrNone) + { + return r; + } + } + + DMultiTouch::iMultiTouchSupported = DMultiTouch::Init(); + + // Create multitouch when necessary + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled() && DMultiTouch::iMultiTouchSupported) + { + TheMultiTouch = new DMultiTouch(systemIni->MultiTouchProximityStep(),systemIni->MultiTouchPressureStep()); + if(!TheMultiTouch) + { + r = KErrNoMemory; + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + } + DMultiTouch::iMultiTouchCreated = TRUE; + } + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + } + +TInt DWinsUi::DoDefineEmulatorControlHotKey(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineEmulatorControlHotKey(aValue); + } + + +TInt DWinsUi::DefineEmulatorControlHotKey(const char* aValue) + { + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt err = KErrNone; + + TEmulCommand command = ENoCommand; + TInt data = 0; + if (_strnicmp(beg, "SelectConfig", end-beg) == 0) + { + //get the int param which is the config to switch to + beg = end; + char * e; + data = strtol(beg, &e,0); + if (beg == e) + err = KErrArgument; + end = e; + command = ESelectConfig; + } + else if(_strnicmp(beg, "NextConfig", end-beg) == 0) + { + command = ENextConfig; + } + else + { + err = KErrArgument; + } + if (err != KErrNone) + return err; + + // get the keys + KeyCombination* pCombination = new KeyCombination(data, command); + if (!pCombination) + return KErrNoMemory; + + beg = skipws(end); + const char* end2; + for (TInt i=0;iAddKey((TStdScanCode)key); + + if (beg == end2 || *end2++ != ',') + break; + beg = end2; + } + return iControlHotKeys.Append(pCombination); + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/gui.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/gui.rc Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,79 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +EPOC_ICON ICON DISCARDABLE "epoc32.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +OVERKEY CURSOR DISCARDABLE "hand.cur" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/hand.cur Binary file emulator/emulatorbsp/specific/hand.cur has changed diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/keyboard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/keyboard.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,817 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\keyboard.cpp +// +// + +#include "gui.h" + +class KeySet + { +public: + struct SEntry + { + const char* iName; + TInt iVal; + }; +public: + inline KeySet(const SEntry aMap[], TInt aSize) + :iMap(aMap), iSize(aSize) + {} + TInt operator[](const TDesC8& aName) const; +private: + const SEntry* iMap; + TInt iSize; + }; + + +const TUint8 StandardKeyMap[KStandardKeyMapSize]= + { + EStdKeyNull, + EStdKeyEscape, + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + EStdKeyMinus, + EStdKeyEquals, + EStdKeyBackspace, + EStdKeyTab, + 'Q', + 'W', + 'E', + 'R', + 'T', + 'Y', + 'U', + 'I', + 'O', + 'P', + EStdKeySquareBracketLeft, + EStdKeySquareBracketRight, + EStdKeyEnter, + EStdKeyLeftCtrl, + 'A', + 'S', + 'D', + 'F', + 'G', + 'H', + 'J', + 'K', + 'L', + EStdKeySemiColon, + EStdKeySingleQuote, + EStdKeyXXX, + EStdKeyLeftShift, + EStdKeyHash, + 'Z', + 'X', + 'C', + 'V', + 'B', + 'N', + 'M', + EStdKeyComma, + EStdKeyFullStop, + EStdKeyForwardSlash, + EStdKeyRightShift, + EStdKeyNkpAsterisk, + EStdKeyLeftFunc, // Alt key used as Func Key + EStdKeySpace, + EStdKeyCapsLock, + EStdKeyMenu, + EStdKeyHelp, + EStdKeyDial, + EStdKeyF4, + EStdKeyF5, + EStdKeyF6, + EStdKeyF7, + EStdKeyF8, + EStdKeyOff, + EStdKeyF10, + EStdKeyPause, + EStdKeyScrollLock, + EStdKeyNkp7, + EStdKeyNkp8, + EStdKeyNkp9, + EStdKeyNkpMinus, + EStdKeyNkp4, + EStdKeyNkp5, + EStdKeyNkp6, + EStdKeyNkpPlus, + EStdKeyNkp1, + EStdKeyNkp2, + EStdKeyNkp3, + EStdKeyNkp0, + EStdKeyNkpFullStop, + EStdKeyNull, + EStdKeyNull, + EStdKeyBackSlash, + EStdKeyF11, + EStdKeyF12 + }; + +const TUint8 ExtendedKeyMap[]= + { +// EStdKeyNumLock, +// EStdKeyNull, +// EStdKeyHome, +// EStdKeyUpArrow, +// EStdKeyPageUp, +// EStdKeyNull, +// EStdKeyLeftArrow, +// EStdKeyNull, +// EStdKeyRightArrow, +// EStdKeyNull, +// EStdKeyEnd, +// EStdKeyDownArrow, +// EStdKeyPageDown, +// EStdKeyInsert, +// EStdKeyDelete + /*1c*/ EStdKeyNkpEnter, + /*1d*/ EStdKeyRightCtrl, + /*1e*/ EStdKeyNull, + /*1f*/ EStdKeyNull, + /*20*/ EStdKeyNull, + /*21*/ EStdKeyNull, + /*22*/ EStdKeyNull, + /*23*/ EStdKeyNull, + /*24*/ EStdKeyNull, + /*25*/ EStdKeyNull, + /*26*/ EStdKeyNull, + /*27*/ EStdKeyNull, + /*28*/ EStdKeyNull, + /*29*/ EStdKeyNull, + /*2a*/ EStdKeyNull, + /*2b*/ EStdKeyNull, + /*2c*/ EStdKeyNull, + /*2d*/ EStdKeyNull, + /*2e*/ EStdKeyNull, + /*2f*/ EStdKeyNull, + /*30*/ EStdKeyNull, + /*31*/ EStdKeyNull, + /*32*/ EStdKeyNull, + /*33*/ EStdKeyNull, + /*34*/ EStdKeyNull, + /*35*/ EStdKeyNkpForwardSlash, + /*36*/ EStdKeyNull, + /*37*/ EStdKeyPrintScreen, // Actually e0 2a e0 37 + /*38*/ EStdKeyRightFunc, + /*39*/ EStdKeyNull, + /*3a*/ EStdKeyNull, + /*3b*/ EStdKeyNull, + /*3c*/ EStdKeyNull, + /*3d*/ EStdKeyNull, + /*3e*/ EStdKeyNull, + /*3f*/ EStdKeyNull, + /*40*/ EStdKeyNull, + /*41*/ EStdKeyNull, + /*42*/ EStdKeyNull, + /*43*/ EStdKeyNull, + /*44*/ EStdKeyNull, + /*45*/ EStdKeyNumLock, + /*46*/ EStdKeyNull, + /*47*/ EStdKeyHome, + /*48*/ EStdKeyUpArrow, + /*49*/ EStdKeyPageUp, + /*4a*/ EStdKeyNull, + /*4b*/ EStdKeyLeftArrow, + /*4c*/ EStdKeyNull, + /*4d*/ EStdKeyRightArrow, + /*4e*/ EStdKeyNull, + /*4f*/ EStdKeyEnd, + /*50*/ EStdKeyDownArrow, + /*51*/ EStdKeyPageDown, + /*52*/ EStdKeyInsert, + /*53*/ EStdKeyDelete, + /*54*/ EStdKeyNull, + /*55*/ EStdKeyNull, + /*56*/ EStdKeyNull, + /*57*/ EStdKeyNull, + /*58*/ EStdKeyNull, + /*59*/ EStdKeyNull, + /*5a*/ EStdKeyNull, + /*5b*/ EStdKeyLeftAlt, //left windows key + /*5c*/ EStdKeyMenu, //right windows key + /*5d*/ EStdKeyHelp //right mouse button key + }; + + +const KeySet::SEntry EPOCKeyNameToKeyMap[] = + { + {"EStdKeyNull",EStdKeyNull}, + {"EStdKeyBackspace",EStdKeyBackspace}, + {"EStdKeyTab",EStdKeyTab}, + {"EStdKeyEnter",EStdKeyEnter}, + {"EStdKeyEscape",EStdKeyEscape}, + {"EStdKeySpace",EStdKeySpace}, + {"EStdKeyPrintScreen",EStdKeyPrintScreen}, + {"EStdKeyPause",EStdKeyPause}, + {"EStdKeyHome",EStdKeyHome}, + {"EStdKeyEnd",EStdKeyEnd}, + {"EStdKeyPageUp",EStdKeyPageUp}, + {"EStdKeyPageDown",EStdKeyPageDown}, + {"EStdKeyInsert",EStdKeyInsert}, + {"EStdKeyDelete",EStdKeyDelete}, + {"EStdKeyLeftArrow",EStdKeyLeftArrow}, + {"EStdKeyRightArrow",EStdKeyRightArrow}, + {"EStdKeyUpArrow",EStdKeyUpArrow}, + {"EStdKeyDownArrow",EStdKeyDownArrow}, + {"EStdKeyLeftShift",EStdKeyLeftShift}, + {"EStdKeyRightShift",EStdKeyRightShift}, + {"EStdKeyLeftAlt",EStdKeyLeftAlt}, + {"EStdKeyRightAlt",EStdKeyRightAlt}, + {"EStdKeyLeftCtrl",EStdKeyLeftCtrl}, + {"EStdKeyRightCtrl",EStdKeyRightCtrl}, + {"EStdKeyLeftFunc",EStdKeyLeftFunc}, + {"EStdKeyRightFunc",EStdKeyRightFunc}, + {"EStdKeyCapsLock",EStdKeyCapsLock}, + {"EStdKeyNumLock",EStdKeyNumLock}, + {"EStdKeyScrollLock",EStdKeyScrollLock}, + {"EStdKeyF1",EStdKeyF1}, + {"EStdKeyF2",EStdKeyF2}, + {"EStdKeyF3",EStdKeyF3}, + {"EStdKeyF4",EStdKeyF4}, + {"EStdKeyF5",EStdKeyF5}, + {"EStdKeyF6",EStdKeyF6}, + {"EStdKeyF7",EStdKeyF7}, + {"EStdKeyF8",EStdKeyF8}, + {"EStdKeyF9",EStdKeyF9}, + {"EStdKeyF10",EStdKeyF10}, + {"EStdKeyF11",EStdKeyF11}, + {"EStdKeyF12",EStdKeyF12}, + {"EStdKeyF13",EStdKeyF13}, + {"EStdKeyF14",EStdKeyF14}, + {"EStdKeyF15",EStdKeyF15}, + {"EStdKeyF16",EStdKeyF16}, + {"EStdKeyF17",EStdKeyF17}, + {"EStdKeyF18",EStdKeyF18}, + {"EStdKeyF19",EStdKeyF19}, + {"EStdKeyF20",EStdKeyF20}, + {"EStdKeyF21",EStdKeyF21}, + {"EStdKeyF22",EStdKeyF22}, + {"EStdKeyF23",EStdKeyF23}, + {"EStdKeyF24",EStdKeyF24}, + {"EStdKeyXXX",EStdKeyXXX}, + {"EStdKeyComma",EStdKeyComma}, + {"EStdKeyFullStop",EStdKeyFullStop}, + {"EStdKeyForwardSlash",EStdKeyForwardSlash}, + {"EStdKeyBackSlash",EStdKeyBackSlash}, + {"EStdKeySemiColon",EStdKeySemiColon}, + {"EStdKeySingleQuote",EStdKeySingleQuote}, + {"EStdKeyHash",EStdKeyHash}, + {"EStdKeySquareBracketLeft",EStdKeySquareBracketLeft}, + {"EStdKeySquareBracketRight",EStdKeySquareBracketRight}, + {"EStdKeyMinus",EStdKeyMinus}, + {"EStdKeyEquals",EStdKeyEquals}, + {"EStdKeyNkpForwardSlash",EStdKeyNkpForwardSlash}, + {"EStdKeyNkpAsterisk",EStdKeyNkpAsterisk}, + {"EStdKeyNkpMinus",EStdKeyNkpMinus}, + {"EStdKeyNkpPlus",EStdKeyNkpPlus}, + {"EStdKeyNkpEnter",EStdKeyNkpEnter}, + {"EStdKeyNkp1",EStdKeyNkp1}, + {"EStdKeyNkp2",EStdKeyNkp2}, + {"EStdKeyNkp3",EStdKeyNkp3}, + {"EStdKeyNkp4",EStdKeyNkp4}, + {"EStdKeyNkp5",EStdKeyNkp5}, + {"EStdKeyNkp6",EStdKeyNkp6}, + {"EStdKeyNkp7",EStdKeyNkp7}, + {"EStdKeyNkp8",EStdKeyNkp8}, + {"EStdKeyNkp9",EStdKeyNkp9}, + {"EStdKeyNkp0",EStdKeyNkp0}, + {"EStdKeyNkpFullStop",EStdKeyNkpFullStop}, + {"EStdKeyMenu",EStdKeyMenu}, + {"EStdKeyBacklightOn",EStdKeyBacklightOn}, + {"EStdKeyBacklightOff",EStdKeyBacklightOff}, + {"EStdKeyBacklightToggle",EStdKeyBacklightToggle}, + {"EStdKeyIncContrast",EStdKeyIncContrast}, + {"EStdKeyDecContrast",EStdKeyDecContrast}, + {"EStdKeySliderDown",EStdKeySliderDown}, + {"EStdKeySliderUp",EStdKeySliderUp}, + {"EStdKeyDictaphonePlay",EStdKeyDictaphonePlay}, + {"EStdKeyDictaphoneStop",EStdKeyDictaphoneStop}, + {"EStdKeyDictaphoneRecord",EStdKeyDictaphoneRecord}, + {"EStdKeyHelp",EStdKeyHelp}, + {"EStdKeyOff",EStdKeyOff}, + {"EStdKeyDial",EStdKeyDial}, + {"EStdKeyIncVolume",EStdKeyIncVolume}, + {"EStdKeyDecVolume",EStdKeyDecVolume}, + {"EStdKeyDevice0",EStdKeyDevice0}, + {"EStdKeyDevice1",EStdKeyDevice1}, + {"EStdKeyDevice2",EStdKeyDevice2}, + {"EStdKeyDevice3",EStdKeyDevice3}, + {"EStdKeyDevice4",EStdKeyDevice4}, + {"EStdKeyDevice5",EStdKeyDevice5}, + {"EStdKeyDevice6",EStdKeyDevice6}, + {"EStdKeyDevice7",EStdKeyDevice7}, + {"EStdKeyDevice8",EStdKeyDevice8}, + {"EStdKeyDevice9",EStdKeyDevice9}, + {"EStdKeyDeviceA",EStdKeyDeviceA}, + {"EStdKeyDeviceB",EStdKeyDeviceB}, + {"EStdKeyDeviceC",EStdKeyDeviceC}, + {"EStdKeyDeviceD",EStdKeyDeviceD}, + {"EStdKeyDeviceE",EStdKeyDeviceE}, + {"EStdKeyDeviceF",EStdKeyDeviceF}, + {"EStdKeyDevice10",EStdKeyDevice10}, + {"EStdKeyDevice11",EStdKeyDevice11}, + {"EStdKeyDevice12",EStdKeyDevice12}, + {"EStdKeyDevice13",EStdKeyDevice13}, + {"EStdKeyDevice14",EStdKeyDevice14}, + {"EStdKeyDevice15",EStdKeyDevice15}, + {"EStdKeyDevice16",EStdKeyDevice16}, + {"EStdKeyDevice17",EStdKeyDevice17}, + {"EStdKeyDevice18",EStdKeyDevice18}, + {"EStdKeyDevice19",EStdKeyDevice19}, + {"EStdKeyDevice1A",EStdKeyDevice1A}, + {"EStdKeyDevice1B",EStdKeyDevice1B}, + {"EStdKeyDevice1C",EStdKeyDevice1C}, + {"EStdKeyDevice1D",EStdKeyDevice1D}, + {"EStdKeyDevice1E",EStdKeyDevice1E}, + {"EStdKeyDevice1F",EStdKeyDevice1F}, + {"EStdKeyDevice20",EStdKeyDevice20}, + {"EStdKeyDevice21",EStdKeyDevice21}, + {"EStdKeyDevice22",EStdKeyDevice22}, + {"EStdKeyDevice23",EStdKeyDevice23}, + {"EStdKeyDevice24",EStdKeyDevice24}, + {"EStdKeyDevice25",EStdKeyDevice25}, + {"EStdKeyDevice26",EStdKeyDevice26}, + {"EStdKeyDevice27",EStdKeyDevice27}, + {"EStdKeyApplication0",EStdKeyApplication0}, + {"EStdKeyApplication1",EStdKeyApplication1}, + {"EStdKeyApplication2",EStdKeyApplication2}, + {"EStdKeyApplication3",EStdKeyApplication3}, + {"EStdKeyApplication4",EStdKeyApplication4}, + {"EStdKeyApplication5",EStdKeyApplication5}, + {"EStdKeyApplication6",EStdKeyApplication6}, + {"EStdKeyApplication7",EStdKeyApplication7}, + {"EStdKeyApplication8",EStdKeyApplication8}, + {"EStdKeyApplication9",EStdKeyApplication9}, + {"EStdKeyApplicationA",EStdKeyApplicationA}, + {"EStdKeyApplicationB",EStdKeyApplicationB}, + {"EStdKeyApplicationC",EStdKeyApplicationC}, + {"EStdKeyApplicationD",EStdKeyApplicationD}, + {"EStdKeyApplicationE",EStdKeyApplicationE}, + {"EStdKeyApplicationF",EStdKeyApplicationF}, + {"EStdKeyApplication10",EStdKeyApplication10}, + {"EStdKeyApplication11",EStdKeyApplication11}, + {"EStdKeyApplication12",EStdKeyApplication12}, + {"EStdKeyApplication13",EStdKeyApplication13}, + {"EStdKeyApplication14",EStdKeyApplication14}, + {"EStdKeyApplication15",EStdKeyApplication15}, + {"EStdKeyApplication16",EStdKeyApplication16}, + {"EStdKeyApplication17",EStdKeyApplication17}, + {"EStdKeyApplication18",EStdKeyApplication18}, + {"EStdKeyApplication19",EStdKeyApplication19}, + {"EStdKeyApplication1A",EStdKeyApplication1A}, + {"EStdKeyApplication1B",EStdKeyApplication1B}, + {"EStdKeyApplication1C",EStdKeyApplication1C}, + {"EStdKeyApplication1D",EStdKeyApplication1D}, + {"EStdKeyApplication1E",EStdKeyApplication1E}, + {"EStdKeyApplication1F",EStdKeyApplication1F}, + {"EStdKeyApplication20",EStdKeyApplication20}, + {"EStdKeyApplication21",EStdKeyApplication21}, + {"EStdKeyApplication22",EStdKeyApplication22}, + {"EStdKeyApplication23",EStdKeyApplication23}, + {"EStdKeyApplication24",EStdKeyApplication24}, + {"EStdKeyApplication25",EStdKeyApplication25}, + {"EStdKeyApplication26",EStdKeyApplication26}, + {"EStdKeyApplication27",EStdKeyApplication27}, + {"EStdKeyYes",EStdKeyYes}, + {"EStdKeyNo",EStdKeyNo}, + {"EStdKeyIncBrightness",EStdKeyIncBrightness}, + {"EStdKeyDecBrightness",EStdKeyDecBrightness}, + {"A", 'A'}, + {"B", 'B'}, + {"C", 'C'}, + {"D", 'D'}, + {"E", 'E'}, + {"F", 'F'}, + {"G", 'G'}, + {"H", 'H'}, + {"I", 'I'}, + {"J", 'J'}, + {"K", 'K'}, + {"L", 'L'}, + {"M", 'M'}, + {"N", 'N'}, + {"O", 'O'}, + {"P", 'P'}, + {"Q", 'Q'}, + {"R", 'R'}, + {"S", 'S'}, + {"T", 'T'}, + {"U", 'U'}, + {"V", 'V'}, + {"W", 'W'}, + {"X", 'X'}, + {"Y", 'Y'}, + {"Z", 'Z'}, + {"0", '0'}, + {"1", '1'}, + {"2", '2'}, + {"3", '3'}, + {"4", '4'}, + {"5", '5'}, + {"6", '6'}, + {"7", '7'}, + {"8", '8'}, + {"9", '9'}, + {"EKeyScreenDimension0",EKeyScreenDimension0<<16}, + {"EKeyScreenDimension1",EKeyScreenDimension1<<16}, + {"EKeyScreenDimension2",EKeyScreenDimension2<<16}, + {"EKeyScreenDimension3",EKeyScreenDimension3<<16} + }; + +const KeySet::SEntry RealKeyNames[] = + { + {"Escape",1}, + {"1",2}, + {"2",3}, + {"3",4}, + {"4",5}, + {"5",6}, + {"6",7}, + {"7",8}, + {"8",9}, + {"9",10}, + {"0",11}, + {"Minus",12}, + {"Equals",13}, + {"BackSpace",14}, + {"Tab",15}, + {"Q",16}, + {"W",17}, + {"E",18}, + {"R",19}, + {"T",20}, + {"Y",21}, + {"U",22}, + {"I",23}, + {"O",24}, + {"P",25}, + {"SquareBracketLeft",26}, + {"SquareBracketRight",27}, + {"Enter",28}, + {"LeftCtrl",29}, + {"A",30}, + {"S",31}, + {"D",32}, + {"F",33}, + {"G",34}, + {"H",35}, + {"J",36}, + {"K",37}, + {"L",38}, + {"SemiColon",39}, + {"SingleQuote",40}, + {"BackTick",41}, + {"LeftShift",42}, + {"Hash",43}, + {"Z",44}, + {"X",45}, + {"C",46}, + {"V",47}, + {"B",48}, + {"N",49}, + {"M",50}, + {"Comma",51}, + {"FullStop",52}, + {"ForwardSlash",53}, + {"RightShift",54}, + {"NkpAsterisk",55}, + {"LeftAlt",56}, // Alt key used as Func Key + {"Space",57}, + {"CapsLock",58}, + {"F1",59}, + {"F2",60}, + {"F3",61}, + {"F4",62}, + {"F5",63}, + {"F6",64}, + {"F7",65}, + {"F8",66}, + {"F9",67}, + {"F10",68}, + {"Pause",69}, + {"ScrollLock",70}, + {"Nkp7",71}, + {"Nkp8",72}, + {"Nkp9",73}, + {"NkpMinus",74}, + {"Nkp4",75}, + {"Nkp5",76}, + {"Nkp6",77}, + {"NkpPlus",78}, + {"Nkp1",79}, + {"Nkp2",80}, + {"Nkp3",81}, + {"Nkp0",82}, + {"NkpFullStop",83}, + {"BackSlash",86}, + {"F11",87}, + {"F12",88} + }; + +const KeySet::SEntry RealExtendedKeyNames[] = + { + {"NkpEnter",0}, + {"RightCtrl",1}, + {"NkpForwardSlash", 25}, + {"PrintScreen",27}, + {"RightAlt", 28}, + {"NumLock", 41}, + {"Home",43}, + {"UpArrow",44}, + {"PageUp",45}, + {"LeftArrow",47}, + {"RightArrow",49}, + {"End",51}, + {"DownArrow",52}, + {"PageDown",53}, + {"Insert",54}, + {"Delete",55}, + {"LeftWindows",63}, + {"RightWindows",64}, + {"ContextMenu",65} + }; + +const KeySet EpocKeys(EPOCKeyNameToKeyMap, sizeof(EPOCKeyNameToKeyMap)/sizeof(KeySet::SEntry)); +const KeySet StandardKeys(RealKeyNames, sizeof(RealKeyNames)/sizeof(KeySet::SEntry)); +const KeySet ExtendedKeys(RealExtendedKeyNames, sizeof(RealExtendedKeyNames)/sizeof(KeySet::SEntry)); + +TInt KeySet::operator[](const TDesC8& aName) const + { + TInt len = aName.Length(); + const char* p = (const char*)aName.Ptr(); + for (const SEntry* e = iMap + iSize; --e >= iMap; ) + { + if (_strnicmp(e->iName, p, len) == 0 && e->iName[len] == '\0') + return e->iVal; + } + return KErrNotFound; + } + +// Class Alias + +Alias::Alias() + :iMap(10) + {} + +TInt Alias::Add(const TDesC8& aAlias, const TDesC8& aName) +// +// add a new alias +// + { + TInt r = KErrNoMemory; + SEntry e; + e.iAlias = HBuf8::New(aAlias); + if (e.iAlias) + { + e.iName = HBuf8::New(aName); + if (e.iName) + { + r = iMap.InsertInOrder(e, &Alias::Compare); + if (r == KErrNone) + return KErrNone; + delete e.iName; + } + delete e.iAlias; + } + return r; + } + +const TDesC8* Alias::operator[](const TDesC8& aAlias) +// +// Look up an alias +// + { + SEntry e; + e.iAlias = const_cast(&aAlias); + TInt ix = iMap.FindInOrder(e, &Alias::Compare); + return ix >= 0 ? iMap[ix].iName : NULL; + } + +TInt Alias::Compare(const SEntry& aLhs, const SEntry& aRhs) + { + return CompareI(*aLhs.iAlias, *aRhs.iAlias); + } + + + +// keyboard mapping + +DWinsKeyboard::DWinsKeyboard() + { + memcpy(iStandardKeyMap, StandardKeyMap, KStandardKeyMapSize); + memcpy(iExtendedKeyMap, ExtendedKeyMap, KExtendedKeyMapSize); + memcpy(iAltStandardKeyMap, StandardKeyMap, KStandardKeyMapSize); + memcpy(iAltExtendedKeyMap, ExtendedKeyMap, KExtendedKeyMapSize); + memcpy(iCtrlStandardKeyMap, StandardKeyMap, KStandardKeyMapSize); + memcpy(iCtrlExtendedKeyMap, ExtendedKeyMap, KExtendedKeyMapSize); + } + +TInt DWinsKeyboard::Init(TInt aId) +// +// Initialise the alias and key maps from the properties +// + { + char property[50]; + wsprintfA(property, "Configuration[%d]DefineKeyName",aId); + TInt r = MultiProperty(&DWinsKeyboard::DoDefineAlias, this, property); + if (r != KErrNone) + return r; + wsprintfA(property, "Configuration[%d]KeyMap",aId); + r = MultiProperty(&DWinsKeyboard::DoMapKey, this, property); + return r; + } + +TInt DWinsKeyboard::DoDefineAlias(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineAlias(aValue); + } + +TInt DWinsKeyboard::DefineAlias(const char* aValue) +// +// The character string terminates in a ';' or a '\0' +// + { + //get the alias name + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TPtrC8 alias((const TUint8*)beg, end-beg); + + //get the real name + beg = skipws(end); + end = skiptok(beg); + TPtrC8 name((const TUint8*)beg, end-beg); + + //prevent an alias being made of an alias + if (iAliasedKeys[name] != NULL) + return KErrArgument; + + // ensure this is valid name + TInt r = GetEPOCKeyCode(name); + if (r == KErrNotFound) + return r; + + //now we need to record the alias name and the real key name + return iAliasedKeys.Add(alias, name); + } + + +TInt DWinsKeyboard::DoMapKey(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->MapKey(aValue); + } + +TInt DWinsKeyboard::MapKey(const char* aValue) + { + //get the win32 name + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + + // check to see if a modifier key has been specified + TBool altModifier = !_strnicmp(beg, "LeftAlt", 7); + altModifier |= !_strnicmp(beg, "RightAlt", 8); + TBool ctrlModifier = !_strnicmp(beg, "LeftCtrl", 8); + ctrlModifier |= !_strnicmp(beg, "RightCtrl", 9); + + // if modifier was found, skip to next token + if (altModifier || ctrlModifier) + { + beg = skipws(end); + end = skiptok(beg); + } + + TPtrC8 name((const TUint8*)beg, end-beg); + + //get the epoc key + beg = skipws(end); + end = skiptok(beg); + TInt key = GetEPOCKeyCode(TPtrC8((const TUint8*)beg, end-beg)); + if (key == KErrNotFound) + return key; + + TInt scancode = StandardKeys[name]; + + // if alt modifier was specified, change the alt key map + if (altModifier) + { + if (scancode >= 0) + iAltStandardKeyMap[scancode] = (TUint8)key; + else + { + scancode = ExtendedKeys[name]; + if (scancode >= 0) + iAltExtendedKeyMap[scancode] = (TUint8)key; + else + return KErrNotFound; + } + } + + // if ctrl modifier was specified, change the ctrl key map + else if (ctrlModifier) + { + if (scancode >= 0) + iCtrlStandardKeyMap[scancode] = (TUint8)key; + else + { + scancode = ExtendedKeys[name]; + if (scancode >= 0) + iCtrlExtendedKeyMap[scancode] = (TUint8)key; + else + return KErrNotFound; + } + } + + // no modifier, change the default key map + else + { + if (scancode >= 0) + iStandardKeyMap[scancode] = (TUint8)key; + else + { + scancode = ExtendedKeys[name]; + if (scancode >= 0) + iExtendedKeyMap[scancode] = (TUint8)key; + else + return KErrNotFound; + } + } + + return KErrNone; + } + +TInt DWinsKeyboard::GetEPOCKeyCode(const TDesC8& aStr) + { + // look for an alias + const TDesC8* arg = iAliasedKeys[aStr]; + return EpocKeys[arg ? *arg : aStr]; + } + +TInt DWinsKeyboard::ScanCodeToKey(TInt aScanCode, const TUint8* aStandardMap, const TUint8* aExtendedMap) +// +// Map Windows scan codes to Epoc key +// + { + TInt stdCode = EStdKeyNull; + TInt extended = aScanCode&KKeyExtendedBit; + aScanCode &= KKeyNormalBits; + if (extended) + { + if (aScanCode >= KExtendedKeyBase && aScanCode <= KMaxExtendedKey) + stdCode = aExtendedMap[aScanCode - KExtendedKeyBase]; + } + else if (aScanCode < KStandardKeyMapSize) + stdCode = aStandardMap[aScanCode]; + return stdCode; + } + +TInt DWinsKeyboard::ScanCodeToStandardKey(TInt aScanCode) +// +// Map Windows scan codes to standard keys +// + { + return ScanCodeToKey(aScanCode, StandardKeyMap, ExtendedKeyMap ); + } + +TInt DWinsKeyboard::ScanCodeToRemappedKey(TInt aScanCode) +// +// Map Windows scan codes to remapped keys +// + { + if (HIBYTE(GetKeyState(VK_MENU))) // Alt key is pressed + return ScanCodeToKey(aScanCode, iAltStandardKeyMap, iAltExtendedKeyMap ); + + if (HIBYTE(GetKeyState(VK_CONTROL))) // Ctrl key is pressed + return ScanCodeToKey(aScanCode, iCtrlStandardKeyMap, iCtrlExtendedKeyMap ); + + return ScanCodeToKey(aScanCode, iStandardKeyMap, iExtendedKeyMap ); + } + + + + +TInt DWinsKeyboard::GetScanCode(const TDesC8& aStr) + { + return StandardKeys[aStr]; + } + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/keymap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/keymap.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,1905 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\keymap.cpp +// The lookup tables giving the function to be carried out +// and the new state of the keyboard +// +// + + +#include + +// the "array" parameter must be a true array and not a pointer +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) + +#define TABLE_ENTRY_ANOTHER_CTRL_DIGIT \ + { \ + { \ + EModifierKeyUp|EModifierFunc, \ + 0 \ + }, \ + { \ + EKeyNull, \ + EAnyDigitGivenRadix \ + }, \ + { \ + EStateCtrlDigits, \ + EAddOnCtrlDigit, \ + 0 \ + } \ + } + +// This table is searched for a match if a match has not been +// found in the current state's table + +LOCAL_D const SFuncTableEntry defaultTable[]= + { + { // prevent key up events generating keycodes + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyNull, + EAnyKey + }, + { + EStateUnchanged, + EDoNothing, + 0 + } + }, + { // prevent any modifer key from changing state + { + 0, + 0 + }, + { + EKeyNull, + EAnyModifierKey + }, + { + EStateUnchanged, + EDoNothing, + 0 + } + }, + { // filter out any unprocessed codes??? + { + 0, + 0 + }, + { + EKeyNull, + EAnyKey + }, + { + EStateNormal, + EDoNothing, + 0 + } + } + }; + +// The table indicating which keys change which modifiers; +// the state field in this table is ignored +LOCAL_D const SFuncTableEntry modifierTable[]= + { + { + { + EModifierKeyUp, + 0 + }, + { + EKeyCapsLock, + EMatchKey + }, + { + EStateUnchanged, + EToggleModifier, + EModifierCapsLock + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyNumLock, + EMatchKey + }, + { + EStateUnchanged, + EToggleModifier, + EModifierNumLock + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyScrollLock, + EMatchKey + }, + { + EStateUnchanged, + EToggleModifier, + EModifierScrollLock + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyLeftAlt, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierAlt|EModifierLeftAlt + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyLeftAlt, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierLeftAlt + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyLeftFunc, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierFunc|EModifierLeftFunc + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyLeftFunc, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierLeftFunc + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyLeftShift, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierShift|EModifierLeftShift + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyLeftShift, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierLeftShift + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyLeftCtrl, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierCtrl|EModifierLeftCtrl + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyLeftCtrl, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierLeftCtrl + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyRightAlt, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierAlt|EModifierRightAlt + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyRightAlt, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierRightAlt + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyRightFunc, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierFunc|EModifierRightFunc + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyRightFunc, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierRightFunc + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyRightShift, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierShift|EModifierRightShift + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyRightShift, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierRightShift + } + }, + { + { + EModifierKeyUp, + 0 + }, + { + EKeyRightCtrl, + EMatchKey + }, + { + EStateUnchanged, + ETurnOnModifier, + EModifierCtrl|EModifierRightCtrl + } + }, + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyRightCtrl, + EMatchKey + }, + { + EStateUnchanged, + ETurnOffModifier, + EModifierRightCtrl + } + } + }; + +// table0 to table12 are the tables corresponding to states +// 0 to 12 respectively + +LOCAL_D const SFuncTableEntry table0[]= + { + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table1[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'e', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAe + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'c', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcCcedilla + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 's', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1EsTset + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOslash + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'd', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcThorn + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 't', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcSoftTh + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'l', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LeftChevron + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'r', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1RightChevron + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'x', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1InvExclam + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'q', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1InvQuest + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAo + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'p', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1Pound + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table2[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'e', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcEumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'i', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcIumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'u', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcUumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'y', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcYumlaut + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + ' ', + EMatchKey + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1SpaceUmlaut + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table3[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAgrave + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'e', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcEgrave + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'i', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcIgrave + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOgrave + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'u', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcUgrave + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + ' ', + EMatchKey + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1SpaceGrave + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table4[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'e', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcEacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'i', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcIacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'u', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcUacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'y', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcYacute + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + ' ', + EMatchKey + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcSpaceAcute + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table5[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAtilde + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'n', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcNtilde + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOtilde + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + ' ', + EMatchKey + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcSpaceTilde + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table6[]= + { + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'a', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcAcirc + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'e', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcEcirc + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'i', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcIcirc + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'o', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcOcirc + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + 'u', + EMatchKeyCaseInsens + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcUcirc + } + }, + { + { + EModifierFunc|EModifierKeyUp, + 0 + }, + { + ' ', + EMatchKey + }, + { + EStateNormal, + EPassSpecialKeyThru, + ELatin1LcSpaceCirc + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table7[]= + { + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table8[]= + { + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table9[]= + { + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTableEntry table10[]= + { + { // check for ctrl-number presses + { + EModifierCtrl|EModifierFunc|EModifierKeyUp, + EModifierCtrl + }, + { + EKeyNull, + EAnyDecimalDigit + }, + { + EStateDerivedFromDigitEntered, + EAddOnCtrlDigit, + 0 + } + }, + { // filter out up key strokes + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyNull, + EAnyKey + }, + { + EStateUnchanged, + EDoNothing, + 0 + } + }, + { // pass thru any non-processed keys + { + 0, + 0 + }, + { + EKeyNull, + EAnyKey + }, + { + EStateUnchanged, + EPassKeyThru, + 0 + } + } + }; + +//LOCAL_D const SFuncTableEntry table11[]= +// { +// TABLE_ENTRY_ANOTHER_CTRL_DIGIT +// }; + +LOCAL_D const SFuncTableEntry table12[]= + { + { + { + EModifierKeyUp, + EModifierKeyUp + }, + { + EKeyLeftCtrl, + EMatchLeftOrRight + }, + { + EStateNormal, + EPassCtrlDigitsThru, + 0 + } + }, + TABLE_ENTRY_ANOTHER_CTRL_DIGIT + }; + +LOCAL_D const SFuncTable genFuncTables[]= + { + { + ARRAY_LENGTH(table0), + &table0[0] + }, + { + ARRAY_LENGTH(table1), + &table1[0] + }, + { + ARRAY_LENGTH(table2), + &table2[0] + }, + { + ARRAY_LENGTH(table3), + &table3[0] + }, + { + ARRAY_LENGTH(table4), + &table4[0] + }, + { + ARRAY_LENGTH(table5), + &table5[0] + }, + { + ARRAY_LENGTH(table6), + &table6[0] + }, + { + ARRAY_LENGTH(table7), + &table7[0] + }, + { + ARRAY_LENGTH(table8), + &table8[0] + }, + { + ARRAY_LENGTH(table9), + &table9[0] + }, + { + ARRAY_LENGTH(table10), + &table10[0] + }, + { + 0, + NULL + }, + { + ARRAY_LENGTH(table12), + &table12[0] + } + }; + +LOCAL_D const SFuncTables FuncTables= + { + { + ARRAY_LENGTH(defaultTable), + &defaultTable[0] + }, + { + ARRAY_LENGTH(modifierTable), + &modifierTable[0] + }, + ARRAY_LENGTH(genFuncTables), + &genFuncTables[0] + }; + +LOCAL_D const SScanCodeBlock scanCodeBlock_unmodifiable[]= + { + {EStdKeyLeftShift, EStdKeyScrollLock} + }; + +LOCAL_D const TUint16 convKeyCodes_unmodifiable[]= + { + EKeyLeftShift, + EKeyRightShift, + EKeyLeftAlt, + EKeyRightAlt, + EKeyLeftCtrl, + EKeyRightCtrl, + EKeyLeftFunc, + EKeyRightFunc, + EKeyCapsLock, + EKeyNumLock, + EKeyScrollLock + }; + +// base: this table traps all of the keyboard's scanCodes except those in convKeyCodes_unmodifiable +LOCAL_D const SScanCodeBlock scanCodeBlock_base[]= + { + {EStdKeyNull, EStdKeyDownArrow}, + {'0', '9'}, + {'A', 'Z'}, + {EStdKeyF1, EStdKeyDial}, + {EStdKeyIncVolume, EStdKeyDecVolume}, + {EStdKeyDevice0,EStdKeyDeviceF}, + {EStdKeyApplication0, EStdKeyApplicationF}, + {EStdKeyYes, EStdKeyDecBrightness}, + {EStdKeyDevice10,EStdKeyDevice1F}, + {EStdKeyApplication10, EStdKeyApplication1F}, + {EStdKeyDevice20,EStdKeyDevice27}, + {EStdKeyApplication20, EStdKeyApplication27} + }; + +// +// This table is internatioalizable +// +LOCAL_D const TUint16 convKeyCodes_base[]= + { + EKeyNull, + EKeyBackspace, + EKeyTab, + EKeyEnter, + EKeyEscape, + ' ', + EKeyPrintScreen, + EKeyPause, + EKeyHome, + EKeyEnd, + EKeyPageUp, + EKeyPageDown, + EKeyInsert, + EKeyDelete, + EKeyLeftArrow, + EKeyRightArrow, + EKeyUpArrow, + EKeyDownArrow, + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + 'y', + 'z', + EKeyF1, + EKeyF2, + EKeyF3, + EKeyF4, + EKeyF5, // Media change emulation + EKeyF6, + EKeyF7, + EKeyF8, // Case close + EKeyF9, // KeyOff + EKeyF10, // SwitchOff + EKeyF11, // Case open + EKeyF12, + EKeyF13, + EKeyF14, + EKeyF15, + EKeyF16, + EKeyF17, + EKeyF18, + EKeyF19, + EKeyF20, + EKeyF21, + EKeyF22, + EKeyF23, + EKeyF24, + '`', + ',', + '.', + '/', + '\\', + ';', + '\'', + '#', + '[', + ']', + '-', + '=', + '/', + '*', + '-', + '+', + EKeyEnter, + EKeyEnd, + EKeyDownArrow, + EKeyPageDown, + EKeyLeftArrow, + EKeyNull, // numeric keypad '5' + EKeyRightArrow, + EKeyHome, + EKeyUpArrow, + EKeyPageUp, + EKeyInsert, + EKeyDelete, + EKeyMenu, + EKeyBacklightOn, + EKeyBacklightOff, + EKeyBacklightToggle, + EKeyIncContrast, + EKeyDecContrast, + EKeySliderDown, + EKeySliderUp, + EKeyDictaphonePlay, + EKeyDictaphoneStop, + EKeyDictaphoneRecord, + EKeyHelp, + EKeyOff, + EKeyDial, + EKeyIncVolume, + EKeyDecVolume, + EKeyDevice0, + EKeyDevice1, + EKeyDevice2, + EKeyDevice3, + EKeyDevice4, + EKeyDevice5, + EKeyDevice6, + EKeyDevice7, + EKeyDevice8, + EKeyDevice9, + EKeyDeviceA, + EKeyDeviceB, + EKeyDeviceC, + EKeyDeviceD, + EKeyDeviceE, + EKeyDeviceF, + EKeyApplication0, + EKeyApplication1, + EKeyApplication2, + EKeyApplication3, + EKeyApplication4, + EKeyApplication5, + EKeyApplication6, + EKeyApplication7, + EKeyApplication8, + EKeyApplication9, + EKeyApplicationA, + EKeyApplicationB, + EKeyApplicationC, + EKeyApplicationD, + EKeyApplicationE, + EKeyApplicationF, + EKeyYes, + EKeyNo, + EKeyIncBrightness, + EKeyDecBrightness, + EKeyDevice10, + EKeyDevice11, + EKeyDevice12, + EKeyDevice13, + EKeyDevice14, + EKeyDevice15, + EKeyDevice16, + EKeyDevice17, + EKeyDevice18, + EKeyDevice19, + EKeyDevice1A, + EKeyDevice1B, + EKeyDevice1C, + EKeyDevice1D, + EKeyDevice1E, + EKeyDevice1F, + EKeyApplication10, + EKeyApplication11, + EKeyApplication12, + EKeyApplication13, + EKeyApplication14, + EKeyApplication15, + EKeyApplication16, + EKeyApplication17, + EKeyApplication18, + EKeyApplication19, + EKeyApplication1A, + EKeyApplication1B, + EKeyApplication1C, + EKeyApplication1D, + EKeyApplication1E, + EKeyApplication1F, + EKeyDevice20, + EKeyDevice21, + EKeyDevice22, + EKeyDevice23, + EKeyDevice24, + EKeyDevice25, + EKeyDevice26, + EKeyDevice27, + EKeyApplication20, + EKeyApplication21, + EKeyApplication22, + EKeyApplication23, + EKeyApplication24, + EKeyApplication25, + EKeyApplication26, + EKeyApplication27 + }; + +// caps-lock: this table traps those scanCodes which are affected by caps-lock +LOCAL_D const SScanCodeBlock scanCodeBlock_capsLock[]= + { + {'A', 'Z'} + }; + +LOCAL_D const TUint16 convKeyCodes_capsLock[]= + { + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + 'Y', + 'Z' + }; + +// shift: this table traps those scanCodes which are affected +// by shift EXCEPT for those scanCodes affected by caps-lock +LOCAL_D const SScanCodeBlock scanCodeBlock_shift[]= + { + {'0', '9'}, + {EStdKeyXXX, EStdKeyEquals}, + }; + +// +// This table is internatioalizable +// +LOCAL_D const TUint16 convKeyCodes_shift[]= + { + ')', + '!', + '"', + ELatin1Pound, + '$', + '%', + '^', + '&', + '*', + '(', + ELatin1LogicNot, + '<', + '>', + '?', + '|', + ':', + '@', + '~', + '{', + '}', + '_', + '+' + }; + +// numlock: this table traps those scanCodes which are affected by numlock +LOCAL_D const SScanCodeBlock scanCodeBlock_numLock[]= + { + {EStdKeyNkpForwardSlash, EStdKeyNkpFullStop} + }; + +LOCAL_D const TUint16 convKeyCodes_numLock[]= + { + '/', + '*', + '-', + '+', + EKeyEnter, + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + '.' + }; + +// ctrl: this table traps those scanCodes which are affected by ctrl +LOCAL_D const SScanCodeBlock scanCodeBlock_ctrl[]= + { +// The space key gets handled else where, otherwise it gets +// thrown away as a NULL key +// {EStdKeySpace, EStdKeySpace}, + + {'A', 'Z'} + }; + +LOCAL_D const TUint16 convKeyCodes_ctrl[]= + { +// 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + }; + +// Rotate by 90: this table traps those scancodes which are affected by the RotateBy90 modifier +LOCAL_D const SScanCodeBlock scanCodeBlock_rotate[]= + { + {'Q', 'Q'}, + {'W', 'W'}, + {'E', 'E'}, + {'A', 'A'}, + {'S', 'S'}, + {'D', 'D'}, + {'Z', 'Z'}, + {'X', 'X'}, + {'C', 'C'}, + }; + +//rotate this 3x3 block of keys 90 degrees clockwise +LOCAL_D const TUint16 convKeyCodes_rot90[]= + { + 'z', + 'a', + 'q', + 'x', + 's', + 'w', + 'c', + 'd', + 'e', + }; + +//rotate this 3x3 block of keys 180 degrees clockwise +LOCAL_D const TUint16 convKeyCodes_rot180[]= + { + 'c', + 'x', + 'z', + 'd', + 's', + 'a', + 'e', + 'w', + 'q', + }; + +//rotate this 3x3 block of keys 90 degrees clockwise +LOCAL_D const TUint16 convKeyCodes_rot270[]= + { + 'e', + 'd', + 'c', + 'w', + 's', + 'x', + 'q', + 'a', + 'z', + }; + +LOCAL_D const SConvSubTable + convSubTable_unmodifiable= + { + &convKeyCodes_unmodifiable[0], + { + ARRAY_LENGTH(scanCodeBlock_unmodifiable), + &scanCodeBlock_unmodifiable[0] + } + }, + convSubTable_base= + { + &convKeyCodes_base[0], + { + ARRAY_LENGTH(scanCodeBlock_base), + &scanCodeBlock_base[0] + } + }, + convSubTable_capsLock= + { + &convKeyCodes_capsLock[0], + { + ARRAY_LENGTH(scanCodeBlock_capsLock), + &scanCodeBlock_capsLock[0] + } + }, + convSubTable_shift= + { + &convKeyCodes_shift[0], + { + ARRAY_LENGTH(scanCodeBlock_shift), + &scanCodeBlock_shift[0] + } + }, + convSubTable_numLock= + { + &convKeyCodes_numLock[0], + { + ARRAY_LENGTH(scanCodeBlock_numLock), + &scanCodeBlock_numLock[0] + } + }, + convSubTable_ctrl= + { + &convKeyCodes_ctrl[0], + { + ARRAY_LENGTH(scanCodeBlock_ctrl), + &scanCodeBlock_ctrl[0] + } + }, + convSubTable_rot90= + { + &convKeyCodes_rot90[0], + { + ARRAY_LENGTH(scanCodeBlock_rotate), + &scanCodeBlock_rotate[0] + } + }, + convSubTable_rot180= + { + &convKeyCodes_rot180[0], + { + ARRAY_LENGTH(scanCodeBlock_rotate), + &scanCodeBlock_rotate[0] + } + }, + convSubTable_rot270= + { + &convKeyCodes_rot270[0], + { + ARRAY_LENGTH(scanCodeBlock_rotate), + &scanCodeBlock_rotate[0] + } + }; + +// Some modifiers, e.g. shift, may required more than one table (other than "base") +// to be searched; therefore arrays of tables are required +LOCAL_D const SConvSubTable + * const convSubTableArray_unmodifiable[]={&convSubTable_unmodifiable}, + * const convSubTableArray_base[]={&convSubTable_base}, + * const convSubTableArray_capsLock[]={&convSubTable_capsLock}, + * const convSubTableArray_shift[]={&convSubTable_capsLock, &convSubTable_shift}, + * const convSubTableArray_capsLockShift[]={&convSubTable_shift}, + * const convSubTableArray_numLock[]={&convSubTable_numLock}, + * const convSubTableArray_ctrl[]={&convSubTable_ctrl}, + * const convSubTableArray_rot90[]={&convSubTable_rot90}, + * const convSubTableArray_rot180[]={&convSubTable_rot180}, + * const convSubTableArray_rot270[]={&convSubTable_rot270}; + +// The order of these nodes is VITAL, as the scanCode/modifiers are +// searched for a match in this order +LOCAL_D const SConvTableNode convTableNodes[]= + { + { + { + 0, /* iMask */ + 0 /* iValue */ + }, /* maskedModifiers */ + ARRAY_LENGTH(convSubTableArray_unmodifiable), /* numSubTables */ + &convSubTableArray_unmodifiable[0] + }, /* pnodes[i] */ + { + { + EModifierCtrl, + EModifierCtrl + }, + ARRAY_LENGTH(convSubTableArray_ctrl), + &convSubTableArray_ctrl[0] + }, + { + { + EModifierNumLock, + EModifierNumLock + }, + ARRAY_LENGTH(convSubTableArray_numLock), + &convSubTableArray_numLock[0] + }, + { + { + EModifierCapsLock|EModifierShift, + EModifierCapsLock + }, + ARRAY_LENGTH(convSubTableArray_capsLock), + &convSubTableArray_capsLock[0] + }, + { + { + EModifierShift|EModifierCapsLock, + EModifierShift + }, + ARRAY_LENGTH(convSubTableArray_shift), + &convSubTableArray_shift[0] + }, + { + { + EModifierCapsLock|EModifierShift, + EModifierCapsLock|EModifierShift + }, + ARRAY_LENGTH(convSubTableArray_capsLockShift), + &convSubTableArray_capsLockShift[0] + }, + { + { + EModifierRotateBy90, + EModifierRotateBy90 + }, + ARRAY_LENGTH(convSubTableArray_rot90), + &convSubTableArray_rot90[0] + }, + { + { + EModifierRotateBy180, + EModifierRotateBy180 + }, + ARRAY_LENGTH(convSubTableArray_rot180), + &convSubTableArray_rot180[0] + }, + { + { + EModifierRotateBy270, + EModifierRotateBy270 + }, + ARRAY_LENGTH(convSubTableArray_rot270), + &convSubTableArray_rot270[0] + }, + { + { + 0, + 0 + }, + ARRAY_LENGTH(convSubTableArray_base), + &convSubTableArray_base[0] + } + }; + +// The top-level exported data structure of all the conversion tables +LOCAL_D const SConvTable ConvTable= + { + ARRAY_LENGTH(convTableNodes), + &convTableNodes[0] + }; + +// The list of scan-codes on the numeric keypad +LOCAL_D const SScanCodeBlock keypadScanCodeBlockArray[]= + { + {EStdKeyNumLock, EStdKeyNumLock}, + {EStdKeyNkpForwardSlash, EStdKeyNkpFullStop} + }; + +LOCAL_D const SScanCodeBlockList ConvTableKeypadScanCodes= + { + ARRAY_LENGTH(keypadScanCodeBlockArray), + &keypadScanCodeBlockArray[0] + }; + +// The list of non-autorepeating key-codes +LOCAL_D const TUint16 nonAutorepKeyCodeArray[]= + { + EKeyEscape, + EKeyPrintScreen, + EKeyPause, + EKeyInsert, + EKeyLeftShift, + EKeyRightShift, + EKeyLeftAlt, + EKeyRightAlt, + EKeyLeftCtrl, + EKeyRightCtrl, + EKeyLeftFunc, + EKeyRightFunc, + EKeyCapsLock, + EKeyNumLock, + EKeyScrollLock, + EKeyMenu, + EKeyDictaphonePlay, + EKeyDictaphoneStop, + EKeyDictaphoneRecord + }; + +LOCAL_D const SKeyCodeList ConvTableNonAutorepKeyCodes= + { + ARRAY_LENGTH(nonAutorepKeyCodeArray), + &nonAutorepKeyCodeArray[0] + }; + +EXPORT_C void KeyDataSettings(TRadix &aRadix,TCtrlDigitsTermination &aCtrlDigitsTermination,TInt &aDefaultCtrlDigitsMaxCount, + TInt &aMaximumCtrlDigitsMaxCount) + { + aRadix=EDecimal; + aCtrlDigitsTermination=ETerminationByCtrlUp; + aDefaultCtrlDigitsMaxCount=3; + aMaximumCtrlDigitsMaxCount=10; + } + +EXPORT_C void KeyDataFuncTable(SFuncTables &aFuncTables) + { + aFuncTables=FuncTables; + } + +EXPORT_C void KeyDataConvTable(SConvTable &aConvTable, TUint &aConvTableFirstScanCode,TUint &aConvTableLastScanCode, + SScanCodeBlockList &aKeypadScanCode,SKeyCodeList &aNonAutorepKeyCodes) + { + aConvTable=ConvTable; + aConvTableFirstScanCode=scanCodeBlock_base[0].firstScanCode; + aConvTableLastScanCode=scanCodeBlock_base[ARRAY_LENGTH(scanCodeBlock_base)-1].lastScanCode; + aKeypadScanCode=ConvTableKeypadScanCodes; + aNonAutorepKeyCodes=ConvTableNonAutorepKeyCodes; + } diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/lffsdev.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/lffsdev.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,642 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\lffsdev.cpp +// +// + +#include +#include +#include + +#define FLASH_FAULT() Kern::Fault("LFFSDEV",__LINE__) + +//#define M18_EMULATION // Test for Control Mode operation + +/******************************************** + * Driver definitions + ********************************************/ + +/** LFFS image name */ +const CHAR KLfsFileName[] = "LFSLDRV.BIN"; + + +//-- default values for LFFS related entries in "epoc.ini" file +const TInt KDefaultFlashSize = 0x400000; //-- "FlashSize" entry, default 4MB +const TInt KEraseBlockSize = 0x20000; //-- "FlashEraseSize" entry, default 128KB +const TUint32 KFlashEraseTime = 1000000; //-- "FlashEraseTime" entry, default 1s +const TInt KWriteBlockSize = 64; //-- "FlashWriteSize" entry +const TInt KFlashWriteTime = 406; //-- "FlashWriteTime" entry, default 406us +const TInt KResumeTime = 5000; //-- "FlashResumeTime" entry, default 5ms + +//-- other possible LFFS related entries in "epoc.ini" file: +//-- "FlashHoldOffTime" default value = iEraseTime/10 + +//-- "FlashForceImgMount" default value = 0. If not 0 LFFS image will be mounted as it is, even if it doesn't have TLfsParams structure in the end. +//-- Moreover, it won't be zero filled and TLfsParams structure won't be written at the end of the image file. +//-- shall be useful for dealing with real images from the real devices + + +/** + This cunning structure is supposed to be at the very end of the LFFS image file. If it is not foung there, + the image gets zero-filled (depends on "FlashForceImgMount" flag in epoc.ini). +*/ + +struct TLfsParams + { + TInt iEraseSize; + }; + +#ifdef _DEBUG +/*************************************************** + * ControlIO command types - for debug builds, only + ***************************************************/ + +enum TCtrlIoTypes + { + //KCtrlIoRww=0, + KCtrlIoTimeout=1 + }; +#endif + + +const TInt KDataBufSize=1024; + +/******************************************** + * Media driver class + ********************************************/ +class DMediaDriverFlashWin32 : public DMediaDriverFlash + { +public: + enum TState + { + EIdle=0, + EWriting=1, + EEraseNoSuspend=2, + EErase=3, + ESuspendPending=4, + ESuspending=5, + ESuspended=6, + EErasePending=7 + }; +public: + DMediaDriverFlashWin32(TInt aMediaId); +public: + // replacing pure virtual - FLASH device specific stuff + virtual TInt Initialise(); + virtual TUint32 EraseBlockSize(); + virtual TUint32 TotalSize(); + virtual TInt DoRead(); + virtual TInt DoWrite(); + virtual TInt DoErase(); + virtual TInt Caps(TLocalDriveCapsV2& caps); +public: + void HandleEvent(); + void StartTimer(TInt aMicros); + void StartErase(); + void SuspendErase(); + void CompleteErase(); + void CompleteWrite(); + void CompleteSuspend(); + void StartPendingRW(); + void ReadFlashParameters(); +public: + static void TimerFn(TAny* aPtr); + static void EventDfc(TAny* aPtr); +#ifdef _DEBUG +public: + enum TCtrlIoState {/*EIdle=0,ECtrlIoWaitWr=1,ECtrlIoWaitRd=2,ECtrlIoWrActive=3,*/ECtrlIoTimeOutPrep=4}; + TInt ControlIO(TInt aCommand,TAny* aParam1,TAny* /*aParam2*/); + TInt Request(TLocDrvRequest& m); +#endif +public: + TState iState; + + TInt iSize; + TInt iEraseBlockSize; + TInt iEraseTime; + TInt iSuspendHoldOffTime; + TInt iResumeTime; + TInt iWriteBlockSize; + TInt iWriteTime; + + HANDLE iFile; + HANDLE iMapping; + TUint8* iBase; + TUint8* iData; // data being written + + NTimer iTimer; + TDfc iEventDfc; + TUint32 iTickPeriod; + TUint32 iEraseCounter; + TUint32 iErasePos; + TInt iTimerExtra; + +#ifdef _DEBUG +public: + TUint8 iCtrlIoState; +#endif + }; + +DMediaDriverFlashWin32::DMediaDriverFlashWin32(TInt aMediaId) + : DMediaDriverFlash(aMediaId), + iTimer(&TimerFn,this), + iEventDfc(&EventDfc,this,NULL,2), + iTickPeriod(NKern::TickPeriod()) + { + // iState=EIdle; +#ifdef _DEBUG + //iCtrlIoState=EIdle; +#endif + + } + +void DMediaDriverFlashWin32::ReadFlashParameters() +// +// Read the flash parameters from the ini file, or use defaults +// + { + + iSize = Property::GetInt("FlashSize", KDefaultFlashSize); + + TInt nblocks = Property::GetInt("FlashEraseBlocks", 0); + if (nblocks == 0) + nblocks = iSize/Property::GetInt("FlashEraseSize", KEraseBlockSize); + + iEraseBlockSize = iSize / nblocks; + __ASSERT_ALWAYS(iEraseBlockSize * nblocks == iSize, FLASH_FAULT()); + __ASSERT_ALWAYS((iEraseBlockSize & (iEraseBlockSize-1)) == 0, FLASH_FAULT()); + + iEraseTime = Property::GetInt("FlashEraseTime", KFlashEraseTime); + + iSuspendHoldOffTime = Property::GetInt("FlashHoldOffTime", iEraseTime/10); + iResumeTime = Property::GetInt("FlashResumeTime", KResumeTime); + iWriteBlockSize = Property::GetInt("FlashWriteSize", KWriteBlockSize); + __ASSERT_ALWAYS((iWriteBlockSize & (iWriteBlockSize-1)) == 0, FLASH_FAULT()); + + iWriteTime = Property::GetInt("FlashWriteTime", KFlashWriteTime); + + } + +TInt DMediaDriverFlashWin32::Initialise() + { + iEventDfc.SetDfcQ(iPrimaryMedia->iDfcQ); + iData=(TUint8*)Kern::Alloc(KDataBufSize); + if (!iData) + return KErrNoMemory; + + ReadFlashParameters(); + + // locate/open the file that models the flash + CHAR filename[MAX_PATH]; + strcpy(filename, Property::GetString("EmulatorMediaPath")); + if (!Emulator::CreateAllDirectories(filename)) + return Emulator::LastError(); + strcat(filename, KLfsFileName); + + iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL); + if (iFile == INVALID_HANDLE_VALUE) + return Emulator::LastError(); + + TLfsParams p; + p.iEraseSize = -1; + DWORD bytes; + TBool valid; + + //-- try to read TLfsParams structure from the end of the image file. + if (SetFilePointer(iFile, iSize, NULL, FILE_BEGIN) != -1 + && ReadFile(iFile, &p, sizeof(TLfsParams), &bytes, NULL) + && p.iEraseSize == iEraseBlockSize) + { + valid = ETrue; //-- read it OK. + } + else + {//-- couldn't read TLfsParams structure from the end of the image file. + //-- if "FlashForceImgMount" parameter from epoc.ini is 0 or not present, + //-- zero-fill the lffs image file and write TLfsParams structure at the end of the file. + + const TInt forceImgMount = Property::GetInt("FlashForceImgMount", 0); + if(!forceImgMount) + { + p.iEraseSize = iEraseBlockSize; + if (SetFilePointer(iFile,iSize, NULL, FILE_BEGIN) == -1 + || !WriteFile(iFile, &p, sizeof(p), &bytes, NULL) + || !SetEndOfFile(iFile)) + return Emulator::LastError(); + + valid = EFalse; + } + else + {//-- mount LFFS image forcingly. + valid = ETrue; + } + } + + iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, iSize, NULL); + if (iMapping == NULL) + return Emulator::LastError(); + + iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, iSize); + if (iBase == NULL) + return Emulator::LastError(); + + //-- zero-fill media image it doesn't contain TLfsParams data at the very end. + if (!valid) + { + memclr(iBase, iSize); + } + + return KErrNone; + } + +TUint32 DMediaDriverFlashWin32::EraseBlockSize() + { + return iEraseBlockSize; + } + +TUint32 DMediaDriverFlashWin32::TotalSize() + { + return iSize; + } + +TInt DMediaDriverFlashWin32::DoRead() + { + if (iWriteReq) + return 1; // write in progress so defer read + + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoRead")); + + if (iState==EErasePending) + { + iTimer.Cancel(); + iState = ESuspended; + } + if (iState==EIdle || iState==ESuspended) + { + // can do the read now + TInt pos=(TInt)iReadReq->Pos(); + TInt len=(TInt)iReadReq->Length(); + + TPtrC8 des(iBase+pos,len); + TInt r=iReadReq->WriteRemote(&des,0); + Complete(EReqRead,r); + if (iState==ESuspended) + StartErase(); + } + else if (iState==EErase) + { + // erase in progress - suspend it + SuspendErase(); + } + else if (iState==EEraseNoSuspend) + iState=ESuspendPending; + // wait for suspend to complete + return KErrNone; + } + +TInt DMediaDriverFlashWin32::DoWrite() + { + if (iReadReq) + return 1; // read in progress so defer write + + if (iState==EErasePending) + { + iTimer.Cancel(); + iState = ESuspended; + } + if (iState==EIdle || iState==ESuspended) + { + // can start the write now + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Write Pos=%08x Length=%08x RemDesOff=%08x", + (TInt)iWriteReq->Pos(),(TInt)iWriteReq->Length(),iWriteReq->RemoteDesOffset())); + if (iState==EIdle) + iState=EWriting; + TInt pos = (TInt)iWriteReq->Pos(); + TInt end = pos + (TInt)iWriteReq->Length(); + pos &= ~(iWriteBlockSize-1); + end = (end + iWriteBlockSize-1) & ~(iWriteBlockSize-1); + StartTimer(((end-pos)/iWriteBlockSize) * iWriteTime); + } + else if (iState==EErase) + { + // erase in progress - suspend it + SuspendErase(); + } + else if (iState==EEraseNoSuspend) + iState=ESuspendPending; + // wait for suspend to complete + return KErrNone; + } + +void DMediaDriverFlashWin32::CompleteWrite() +// +// Do the actual write in the completion +// Transfer data in blocks from the client and AND it to the 'flash' +// + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:WriteComplete")); + + TInt r = KErrNone; + TUint8* flash = iBase + (TInt)iWriteReq->Pos(); + TInt len = (TInt)iWriteReq->Length(); + TInt offset = 0; + while (len > 0) + { + TInt size = Min(len, KDataBufSize); + TPtr8 des(iData,size); + r = iWriteReq->ReadRemote(&des, offset); + if (r!=KErrNone) + break; + len -= size; + offset += size; + const TUint8* ptr = iData; + do + { + *flash++ &= *ptr++; + } while (--size > 0); + } + + if (iState == EWriting) + iState = EIdle; + Complete(EReqWrite,r); + if (iState == ESuspended) + StartErase(); + } + +TInt DMediaDriverFlashWin32::DoErase() + { + if (iReadReq || iWriteReq) + return 1; // read or write in progress so defer this request + TInt pos=(TUint32)iEraseReq->Pos(); + TInt len=(TUint32)iEraseReq->Length(); + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoErase %d@%08x",len,pos)); + if (len!=iEraseBlockSize) + return KErrArgument; // only allow single-block erase + if (pos & (iEraseBlockSize-1)) + return KErrArgument; // start position must be on erase block boundary + __ASSERT_ALWAYS(iState==EIdle,FLASH_FAULT()); + iErasePos=pos; + StartErase(); + return KErrNone; + } + +void DMediaDriverFlashWin32::StartTimer(TInt aMicros) + { + aMicros += iTimerExtra - (iTickPeriod>>1); + if (aMicros < 0) + { + iTimerExtra = aMicros + (iTickPeriod>>1); + iEventDfc.Enque(); // go off 'immediately' + } + else + { + iTimerExtra = 0; + iTimer.OneShot(aMicros / iTickPeriod); + } + } + +void DMediaDriverFlashWin32::TimerFn(TAny* aPtr) + { + ((DMediaDriverFlashWin32*)aPtr)->iEventDfc.Add(); + } + +void DMediaDriverFlashWin32::EventDfc(TAny* aPtr) + { + ((DMediaDriverFlashWin32*)aPtr)->HandleEvent(); + } + +void DMediaDriverFlashWin32::HandleEvent() + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Event %d", iState)); + switch (iState) + { + case ESuspended: + case EWriting: // write completed + { +#ifdef _DEBUG + if(iCtrlIoState==ECtrlIoTimeOutPrep) + { + iState=EIdle; + iCtrlIoState=EIdle; + Complete(EReqWrite,KErrNotReady); + } + else +#endif + CompleteWrite(); + break; + } + case EEraseNoSuspend: + { +#ifdef _DEBUG + if(iCtrlIoState==ECtrlIoTimeOutPrep) + { + iState=EIdle; + iCtrlIoState=EIdle; + Complete(EReqErase,KErrNotReady); + } + else + { +#endif + TInt remain = iEraseCounter - NKern::TickCount(); + if (remain <= 0) + CompleteErase(); + else + { + iState=EErase; + StartTimer(remain * iTickPeriod); + } +#ifdef _DEBUG + } +#endif + break; + } + case EErasePending: + StartErase(); + break; + case EErase: // erase completed + CompleteErase(); + break; + case ESuspendPending: + if (TInt(iEraseCounter - NKern::TickCount()) <= 0) + CompleteErase(); + else + SuspendErase(); + break; + case ESuspending: + CompleteSuspend(); + break; + default: + __KTRACE_OPT(KPANIC,Kern::Printf("iState=%d",iState)); + FLASH_FAULT(); + } + } + +void DMediaDriverFlashWin32::StartErase() +// +// Continue an erase - iEraseCounter has the remaining time for the erase +// + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:StartErase %08x",iBase+iErasePos)); + switch (iState) + { + case ESuspended: + iState = EErasePending; + StartTimer(iResumeTime); + break; + case EIdle: // starting to erase + iEraseCounter = iEraseTime; + case EErasePending: + { + iState = EEraseNoSuspend; + TUint32 remain = iEraseCounter; + iEraseCounter = NKern::TickCount() + remain/iTickPeriod; + StartTimer(Min(remain, iSuspendHoldOffTime)); + } + break; + default: + __KTRACE_OPT(KPANIC,Kern::Printf("iState=%d",iState)); + FLASH_FAULT(); + } + } + +void DMediaDriverFlashWin32::SuspendErase() + { + __ASSERT_ALWAYS(iState==EErase || iState==ESuspendPending,FLASH_FAULT()); + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:SuspendErase %08x",iBase+iErasePos)); + iTimer.Cancel(); + TInt remain = Max(0, TInt(iEraseCounter - NKern::TickCount())); + iEraseCounter = remain * iTickPeriod; + iState = ESuspending; + StartTimer(0); + } + +void DMediaDriverFlashWin32::CompleteSuspend() + { + // erase suspend completion + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:SuspendComplete")); + + iState = ESuspended; + // start any pending read or write requests + StartPendingRW(); + } + +void DMediaDriverFlashWin32::CompleteErase() +// +// Do the actual erase in the completion +// + { + // erase completion + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:EraseComplete")); + + memset(iBase + iErasePos, 0xff, iEraseBlockSize); + + // complete the erase request + iState = EIdle; + Complete(EReqErase,KErrNone); + + // start any pending read or write requests + StartPendingRW(); + } + + +void DMediaDriverFlashWin32::StartPendingRW() + { + // start any pending read or write requests + if (iReadReq) + DoRead(); + if (iWriteReq) + DoWrite(); + } + +#ifdef _DEBUG +// Override the base class version in order to provide access to ControlIO +// +TInt DMediaDriverFlashWin32::Request(TLocDrvRequest& m) + { + TInt r; + TInt id=m.Id(); + __KTRACE_OPT(KLOCDRV,Kern::Printf(">DMediaDriverFlashWin32::Request %d",id)); + if (id!=DLocalDrive::EControlIO) + { + r=DMediaDriverFlash::Request(m); + return r; + } + r=ControlIO((TInt)m.iArg[0],m.iArg[1],m.iArg[2]); + DMediaDriver::Complete(m,r); + return r; + } + +TInt DMediaDriverFlashWin32::ControlIO(TInt aCommand,TAny* /*aParam1*/,TAny* /*aParam2*/) + { + switch (aCommand) + { + case(KCtrlIoTimeout): + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoControlIO invoked for KCtrlIoTimeout")); + // The aim of this test is simulate a flash timeout (and so exercise the consequent + // actions of the software that initiated the request) + if(iCtrlIoState!=EIdle) + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ControlIO request before previous completed")); + return KErrServerBusy; + } + else + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ControlIO timeout initiated")); + iCtrlIoState=ECtrlIoTimeOutPrep; + } + break; + } + + default: + { + __KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ERROR - unrecognised ControlIO command %d",aCommand)); + FLASH_FAULT(); + break; + } + } + return KErrNone; + } + +#endif + +TInt DMediaDriverFlashWin32::Caps(TLocalDriveCapsV2& aCaps) +// On return, aCaps data contains capability information about the +// flash device, in the form of a class derived from TLocalDriveCapsV2. +// The size of the derived class should not exceed KMaxLocalDriveCapsLength +// which is defined and used in e32\drivers\locmedia\locmedia.cpp. If a +// larger sized capabilities class is used, and this code is modified to +// write to member data beyond KMaxLocalDriveCapsLength this will cause a +// fault. + { + // Invoke the base class method then update the sizes for + // Control Mode and Object Mode as required. + DMediaDriverFlash::Caps(aCaps); +#if defined (M18_EMULATION) + TLocalDriveCapsV7* caps = &((TLocalDriveCapsV7&)(aCaps)); + caps->iControlModeSize=16; + caps->iObjectModeSize=1024; + __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) ControlModeSize UPDATED as=0x%x", caps->iControlModeSize) ); + __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) ObjectModeSize UPDATED as=0x%x", caps->iObjectModeSize) ); +#endif + return KErrCompletion; // synchronous completion + } + +DMediaDriverFlash* DMediaDriverFlash::New(TInt aDevice) + { + return new DMediaDriverFlashWin32(aDevice); + } + + + + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/mmc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/mmc.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,1444 @@ +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// PP_MMC.CPP +// +// + +#include "plat_priv.h" +#include +#include "variant.h" +#include "variantmediadef.h" +#include "mmci.h" + +//#define __CARD0_NOT_LOCKABLE__ +//#define __CARD1_NOT_LOCKABLE__ + +const TInt KDiskSectorSize=512; + +TInt DWinsMMCStack::TotalMDiskSize=0; ///< mmc card size for emulator +TUint DWinsMMCStack::CSIZE=0; ///< mmc card size field +TUint DWinsMMCStack::CSIZE_MULT=0; ///< mmc card size field + +TInt DWinsMMCStack::TotalWinsMMC_CardSlots = KDefault_TotalWinsCardSlots; ///< total number of MMC card slots for the emulator +TInt DWinsMMCStack::TotalWinsMMC_Cards = KDefault_TotalWinsCards; ///< total number of MMC cards for the emulator + + +const TUint32 KCsdStructure = 0x01; /* CSD Version No 1.1 */ +const TUint32 KCsdSpecVers = 0x03; /* Version 3.1 */ + +TInt MapLastErrorEpoc() +// +// Map an NT error to an Epoc/32 error. +// + { + TInt res=KErrGeneral; + switch (GetLastError()) + { + case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break; + case ERROR_LOCK_VIOLATION : res=KErrLocked; break; + case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break; + case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + res=KErrAlreadyExists; + break; + case ERROR_NOT_READY: res=KErrNotReady; break; + case ERROR_UNRECOGNIZED_VOLUME: + case ERROR_NOT_DOS_DISK: + res=KErrUnknown; + break; + case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break; + case ERROR_INVALID_NAME: res=KErrBadName; break; + case ERROR_NO_MORE_FILES: res=KErrEof; break; + } + return(res); + } + +TMMCErr MapLastErrorMmc() +// +// Map an NT error to a TMMCErr error. +// + { + DWORD r=GetLastError(); + TInt res=KErrGeneral; + switch (r) + { + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + res=KMMCErrLocked; // KErrLocked + break; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + res=KMMCErrNotFound; // KErrNotFound + break; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + res=KMMCErrAlreadyExists; // KErrAlreadyExists + break; + case ERROR_NOT_READY: res=KMMCErrNoCard; break; + case ERROR_UNRECOGNIZED_VOLUME: + case ERROR_NOT_DOS_DISK: + res=KMMCErrGeneral; // KErrGeneral + break; + case ERROR_UNRECOGNIZED_MEDIA: + case ERROR_INVALID_NAME: + case ERROR_NO_MORE_FILES: + res=KMMCErrResponseCRC; // KErrCorrupt + break; + } + return(res); + } + + +void DWinsMMCStack::MachineInfo(TMMCMachineInfo& aMachineInfo) +// +// Return machine info relating to this MultiMediaCard Stack +// + { + aMachineInfo.iTotalSockets=TotalWinsMMC_CardSlots; + aMachineInfo.iTotalMediaChanges=0; // Not used at present + aMachineInfo.iTotalPrimarySupplies=0; // Not used at present + + aMachineInfo.iFlags = TMMCMachineInfo::ESupportsDoubleBuffering; + aMachineInfo.iBaseBusNumber=0; + + __KTRACE_OPT(KPBUS1,Kern::Printf("MaxReadBlLen(); + const TUint32 blkMsk = blkLen - 1; +#ifdef _DEBUG + __ASSERT_DEBUG(aCard->CSD().ReadBlPartial(), Panic(EWinsMMCAPRNotSupp)); + __ASSERT_DEBUG(aEnd - aStart <= blkLen, Panic(EWinsMMCAPRRange)); + __ASSERT_DEBUG((aEnd & ~blkMsk) > (aStart & ~blkMsk), Panic(EWinsMMCAPRBoundary)); +#endif + + *aPhysStart = aStart & ~blkMsk; + *aPhysEnd = *aPhysStart + blkLen; + } + +void DWinsMMCStack::GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen) + { + *aMDBuf = iMDBuf; + *aMDBufLen = iMDBufLen; + } + +void DWinsMMCStack::Panic(TWinsMMCPanic aPanic) + { + _LIT(KPncNm,"PBUS-MMC-WINS"); + Kern::PanicCurrentThread(KPncNm,aPanic); + } + +DWinsMMCStack::DWinsMMCStack(TInt aBus, DMMCSocket* aSocket) + :DMMCStack(aBus, aSocket) + { + +// iAddressedCard=0; +// iSecureArgDevAddr=0; +// iSecureArgTotalLength=0; +// iCMD42Failed=EFalse; + } + + +/** + Allocate cards. Only called at bootup, so no cleanup if fails. +*/ +TInt DWinsMMCStack::Init() + { + + //-- try to read number of mmc cards and slots from epoc.ini file + const TInt MmcSlots = Property::GetInt("MultiMediaCardSlots"); + const TInt MmcCards = Property::GetInt("MultiMediaCardsNum"); + + if(MmcSlots == 0 && MmcCards == 0) + {//-- parameters not specified, do nothing; static variables are initialized with default values + } + else + { + if((MmcSlots == 0 && MmcCards >0) || (MmcSlots > 0 && MmcCards ==0)) + {//-- only one of the parameters is specified. use it as "Cards quantity" + TotalWinsMMC_Cards = Max(MmcSlots, MmcCards); //-- chose non zero value + TotalWinsMMC_CardSlots = Max(1, TotalWinsMMC_Cards-1); + } + else + {//-- both parameters are specified + TotalWinsMMC_Cards = MmcCards; + TotalWinsMMC_CardSlots = MmcSlots; + } + + }//if(!MmcSlots && !MmcCards) + + TotalWinsMMC_Cards = Min(TotalWinsMMC_Cards, KMax_TotalWinsCards); + TotalWinsMMC_CardSlots = Min(TotalWinsMMC_CardSlots, KMax_TotalWinsCardSlots); + + + if((iCardArray = new TMMCardArray(this)) == NULL) + return KErrNoMemory; + + TInt r=DMMCStack::Init(); + if(r!=KErrNone) + return r; + + DMediaChangeBase* pMCBase = MMCSocket()->iMediaChange; + static_cast(pMCBase)->SetStackP(this); + Wins::SetMediaChangeCallBackPtr(DWinsMMCMediaChange::MediaChangeCallBack, (TAny*)pMCBase); + + // + // Over time memory can become fragmented, and so it is not possible to + // allocate physically contiguous pages. Therefore, the buffers for IO + // are allocated at startup. + // + // For the WINS implementation, fragmentation does not matter because + // DMA is not used. The memory must still be allocated here so MEDMMC is + // able to use it. + // + // The constant calculations could be folded, but this illustrates how the + // values are derived. + // + + // MMC only - values from Hitachi 16Mb card, datasheet HB288016MM1 + + // minor buffer must contain enough space for MBR or block + const TUint mmcBlkSzLog2 = 9; // READ_BLK_LEN and WRITE_BLK_LEN + const TUint mmcBlkSz = 1 << mmcBlkSzLog2; + const TInt mmcMinorBufLen = Max(KDiskSectorSize, mmcBlkSz); + + // There are 2 slots each with up to 2 media drivers; we allocate 8 blocks for each driver. + // It is the media drivers' responsibility to devide up the buffer space according + // to which slot number is allocated to it (DMmcMediaDriverFlash::iCardNumber) + const TInt KMinMMCBlocksInBuffer = 16 * MMC0_NUMMEDIA; + const TInt mmcCchBufLen = KMinMMCBlocksInBuffer << mmcBlkSzLog2; + + const TInt mmcTotalBufLen = mmcMinorBufLen + mmcCchBufLen; + + const TInt totalBufLen = mmcTotalBufLen; + + iMDBuf = reinterpret_cast(Kern::Alloc(totalBufLen)); + iMDBufLen = totalBufLen; + + // setup card size parameters from epoc.ini + if (TotalMDiskSize==0) + { + // Static member variable TotalMDiskSize initialised to zero by default. Set + // up static member variables TotalMDiskSize, CSIZE and CSIZE_MULT once and + // once only. Use INI file setting if available. Else set to default, IMb. + TUint cardSize = Property::GetInt("MultiMediaCardSize"); + if (cardSize) + { + // set values to match epoc.ini settings + SetupDiskParms(cardSize); + } + else + { + // set default values for 1 MB drive + TotalMDiskSize=0x100000; + CSIZE=127; + CSIZE_MULT=2; + } + } + + // Initialise each virtual card that will be used on this stack. + TInt i; + for (i=0 ; i fn8(_L8(emulatorPath)); + fn8.Append(_L8("MMCCRD")); + fn8.AppendNum(aCardNum); + fn8.Append(_L8("A.BIN")); + fn8.Append('\0'); + *aHandle = CreateFileA( + (LPCSTR) fn8.Ptr(), // LPCSTR lpFileName, + GENERIC_READ | GENERIC_WRITE, // DWORD dwDesiredAccess + FILE_SHARE_READ | FILE_SHARE_WRITE, // DWORD dwShareMode + NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes + aCreateNew ? CREATE_ALWAYS : OPEN_ALWAYS, // DWORD dwCreationDisposition + FILE_FLAG_RANDOM_ACCESS, // DWORD dwFlagsAndAttributes + NULL); // HANDLE hTemplateFile + + TInt fileSize=GetFileSize(*aHandle,NULL); + if (fileSize>TotalMDiskSize) + // + // The Drive file already exists and size of emulated drive as configured in + // epoc.ini has been reduced. Musn't corrupt the emulated drive so delete the + // drive file and start from scratch. The emulated drive contents will be + // erased. + // + { + CloseHandle(*aHandle); + DeleteFileA( + (LPCSTR) fn8.Ptr()); // LPCSTR lpFileName, + *aHandle = CreateFileA( + (LPCSTR) fn8.Ptr(), // LPCSTR lpFileName, + GENERIC_READ | GENERIC_WRITE, // DWORD dwDesiredAccess + FILE_SHARE_READ | FILE_SHARE_WRITE, // DWORD dwShareMode + NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes + aCreateNew ? CREATE_ALWAYS : OPEN_ALWAYS, // DWORD dwCreationDisposition + FILE_FLAG_RANDOM_ACCESS, // DWORD dwFlagsAndAttributes + NULL); // HANDLE hTemplateFile + } + + if (*aHandle==INVALID_HANDLE_VALUE) + return(MapLastErrorEpoc()); + + if (SetFilePointer(*aHandle,TotalMDiskSize,NULL,FILE_BEGIN)==0xffffffffu + || ! SetEndOfFile(*aHandle) ) + { + CloseHandle(*aHandle); + return(MapLastErrorEpoc()); + } + + return KErrNone; + } + + +TInt DWinsMMCStack::SetupSimulatedCard(TInt aCardNum) +// +// allocate individual card with Win32 file. Only called at bootup, so no cleanup if fails. +// + { + TWinsCardInfo* cip = new TWinsCardInfo; + if (cip == 0) + return(KErrNoMemory); + + TUint8 cid[KMMCCIDLength]; + cid[0] = 'C'; + cid[1] = 'I'; + cid[2] = 'D'; + cid[3] = TUint8('0' + aCardNum); + TInt j; + for (j = 4; j < KMMCCIDLength - 1; ++j) + cid[j] = 'c'; + cid[KMMCCIDLength - 1] = '#'; // '#' = 0x23, bit zero must be 1 + cip->iCID=cid; + + cip->iPWD=new TMediaPassword; + if (!cip->iPWD) + { + delete cip; + return(KErrNoMemory); + } + + cip->iState=ECardStateIdle; + + HANDLE h=NULL; + TInt err; + if ( (err=CreateBinFileForCard(aCardNum,&h))!=KErrNone ) + { + delete cip; + return(err); + } + cip->iWinHandle=h; + iCardPool[aCardNum]=cip; + return(KErrNone); + } + +void DWinsMMCStack::SetBusConfigDefaults(TMMCBusConfig& aConfig, TUint aClock) +// +// Fills BusConfig structure with default values +// + { + const TUint KWinsMaxHwInterfaceClk=104000; + const TUint KWinsResponseTimeOut=6400; + const TUint KWinsDataTimeOut=40000; + const TUint KWinsBusyTimeOut=200000; + + aConfig.iBusClock = (aClock > KWinsMaxHwInterfaceClk) ? KWinsMaxHwInterfaceClk : aClock; + aConfig.iResponseTimeOut=KWinsResponseTimeOut; + aConfig.iDataTimeOut=KWinsDataTimeOut; + aConfig.iBusyTimeOut=KWinsBusyTimeOut; + } + +void DWinsMMCStack::InitClockOff() +// +// Switch of the identification mode clock and enable the data transfer mode +// clock instead. +// + { + // empty. + } + +void DWinsMMCStack::ASSPReset() +// +// Stop all activities on the host stack +// + { + // empty. + } + +void DWinsMMCStack::ASSPDisengage() +// +// Forced release of all ASSP resources +// + { + } + +void DWinsMMCStack::DoPowerDown() +// +// Power down the bus +// + { + // Change the state of all virtual cards present to Idle + for (TInt i=0 ; iiState=ECardStateIdle; + } + + +LOCAL_C TInt SetMediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,const TDesC8& aPasswd) +// +// Set the password for local drive 'aLocalDrive', card number 'aCardNum' to 'aPasswd' - as an +// environment variable. Note that the card number is only relevant where the emulated drive +// supports card hot-swapping (i.e. F4 whilst F5 is held down). +// + { + // Setup the appropriate environment variable string '_EPOC_LocDrv__PWORD_' + TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y"; + + envVar[13]=(TUint16)('0'+aSocketNum); + envVar[21]=(TUint16)('0'+aCardNum); + + // Setup the new value of the environment variable + TUint16 envVal[100]; + TInt len=aPasswd.Length(); + + // the password may be empty if a card's password is cleared + if (len>(100-1)) + return(KErrArgument); + memcpy(&envVal[0],reinterpret_cast(aPasswd.Ptr()),len); + envVal[len>>1]='\0'; + + // Now set the new value for the environment variable + if (SetEnvironmentVariable(envVar,&envVal[0])) + return(KErrNone); + + return KErrGeneral; + } + +LOCAL_C TInt MediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,TDes8& aPasswd) +// +// Get the password for local drive 'aLocalDrive', card number 'aCardNum' into 'aPasswd' - from +// an environment variable. Note that the card number is only relevant where the emulated drive +// supports card hot-swapping (i.e. F4 whilst F5 is held down). +// + { + TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y"; + + envVar[13]=(TUint16)('0'+aSocketNum); + envVar[21]=(TUint16)('0'+aCardNum); + + TUint16 envVal[100]; // To hold the value of the retreived environment variable + + DWORD len=GetEnvironmentVariable(envVar,&envVal[0],100); + if (len>(TUint)100) + return(KErrGeneral); + if (len) + { + // Found the requested environment variable so there is a password for this local drive / card. + if ((len<<1)<=KMaxMediaPassword) + { + aPasswd.FillZ(KMaxMediaPassword); + aPasswd.Zero(); + aPasswd.Copy(reinterpret_cast(&envVal[0]),len<<1); + return(KErrNone); + } + else + return(KErrGeneral); + } + + return(KErrNotFound); + } + +TMMCErr DWinsMMCStack::DoPowerUpSM() +// +// State Machine functions implemented in ASSP layer +// + { + enum states + { + EStBegin=0, + EStEnd + }; + + SMF_BEGIN + + __KTRACE_OPT(KPBUS1, Kern::Printf("DoPowerUpSM: BEGIN")); + + if( MMCSocket()->iVcc->SetState(EPsuOnCurLimit) != KErrNone ) + return( KMMCErrHardware ); + + for (TInt i=0 ; i=0 && MediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[i]->iPWD))==KErrNone) + { + // Card has a password so lock it automatically on power up. + iCardInfo[i]->iIsLocked=(iCardInfo[i]->iPWD->Length() > 0); + } + else + iCardInfo[i]->iIsLocked=EFalse; + + iCardInfo[i]->iRCA=0x0001; // Default RCA - spec 2.2, s4.2.1, 5.4 + } + + ReportPowerUp(); + + SMF_END + } + +TMMCErr DWinsMMCStack::InitClockOnSM() +// +// Switch on the identification mode clock +// + { + enum states + { + EStBegin=0, + EStEnd + }; + SMF_BEGIN + + SMF_END + } + +TMMCErr DWinsMMCStack::ModifyCardCapabilitySM() +// +// This function provides a chance to modify the capability of paticular cards. +// Licensee may overide this function to modify certain card's capability as needed. +// A state machine is needed in derived function and function of base class should be +// called in order to act more generic behaviour. +// + { + enum states + { + EStBegin=0, + EStDone, + EStEnd + }; + + SMF_BEGIN + + SMF_INVOKES( DMMCStack::BaseModifyCardCapabilitySMST, EStDone ) + + SMF_STATE(EStDone) + + SMF_END + } + +TInt DWinsMMCStack::GetTargetSlotNumber(TBool anRCASupplied,const TRCA& anRCA) +// +// Attempt to determine the slot number of the target card. If the received command +// contained an RCA then 'anRCASupplied' will be ETrue - in which case, 'anRCA' +// contains the RCA in question. +// + { + TInt selCardIdx = KBroadcastToAllCards; + + // if an RCA was supplied, then work out which card slot it corresponds to + if (anRCASupplied) + { + for (TInt i = 0 ; i < TotalWinsMMC_CardSlots ; ++i) + { + if (iCardInfo[i]->iRCA==anRCA) + { + selCardIdx=i; + break; + } + } + } + // else search for currently selected card + else + { + for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i) + { + if (iCardInfo[i]->iState == ECardStateTran) + { + selCardIdx = i; + break; + } + } + } + + return(selCardIdx); + } + +TMMCErr DWinsMMCStack::IssueMMCCommandSM() +// +// Top level ASSP command executor +// + { + enum states + { + EStBegin=0, + EStDoubleBuffer, + EStCommandDone, + EStEnd + }; + + TMMCCommandDesc& cmd = Command(); + + TRCA tgtRCA=0; + TBool supRCA=EFalse; + // Record the RCA if it is embedded in the argument [31:16]. + if (cmd.iCommand == ECmdSetRelativeAddr || cmd.iCommand == ECmdSelectCard + || cmd.iCommand == ECmdSendCSD || cmd.iCommand == ECmdSendCID + || cmd.iCommand == ECmdSendStatus || cmd.iCommand == ECmdGoInactiveState + || cmd.iCommand == ECmdFastIO || cmd.iCommand == ECmdAppCmd ) + { + supRCA=ETrue; + tgtRCA=TUint16(cmd.iArgument >> 16); + } + + // Attempt to determine the target card using supplied RCA + TInt selCardIdx=GetTargetSlotNumber(supRCA,tgtRCA); + + // Simulation of card swapping (i.e. F4/F5) is performed on slot 0. If this is currently + // set to simulate no card present and the issued command is targetted specifically at the + // card in slot 0 (i.e. not a broadcast command) then timeout. + if (selCardIdx==0 && *Wins::CurrentPBusDevicePtr() < 0) + return(KMMCErrResponseTimeOut); + + // If an RCA was supplied but didn't coincide with the RCAs of any cards present + // then timeout (Ignore SET_RCA and APP_CMD as these are sent before RCAs are assigned). + if (supRCA && selCardIdx==KBroadcastToAllCards && + cmd.iCommand != ECmdSetRelativeAddr && cmd.iCommand != ECmdAppCmd) + return(KMMCErrResponseTimeOut); + + HANDLE winHandle=NULL; + + // CMD42 is a data transfer command. That means the R1 response that it returns + // immediately is the state it is in on receiving the data block, and not after + // processing it. If the data block is invalid then LOCK_UNLOCK_FAILED will be + // set in the R1 response which is sent in reply to the next command. + + TBool nextCMD42Failed = EFalse; + TBool lock_unlock_failed=EFalse; + + // When the card is locked, it will only respond to basic command class (0) and + // lock card command class (7). An exception is CMD16. This is sent before CMD42, + // but is classified (MMC Spec 23.2, table 5) as belonging to classes 2 and 4. + // For data transfer commands, LOCK_UNLOCK_FAIL is set in response to the following + const TMMCCommandEnum origCmd(cmd.iCommand); + if ( selCardIdx != KBroadcastToAllCards + && iCardInfo[selCardIdx]->iIsLocked // If locked and not in CCC 0 or 7 then skip + && ( ((cmd.iSpec.iCommandClass & (KMMCCmdClassBasic | KMMCCmdClassLockCard)) == 0) + && cmd.iCommand != ECmdSetBlockLen ) ) + { + lock_unlock_failed = ETrue; // try to access locked card + cmd.iCommand = TMMCCommandEnum(-1); // skip command processing + } + + SMF_BEGIN + + TBool rto = EFalse; // response timeout + switch (cmd.iCommand) + { + case ECmdGoIdleState: // CMD0 + { + for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i) + iCardInfo[i]->iState = ECardStateIdle; + } + break; + + case ECmdSendOpCond: // CMD1 + { + for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i) + iCardInfo[i]->iState = ECardStateReady; + + // bit32 is set to indicate cards are not still powering up + TUint32 r3 = KMMCWinsCardOCRValue | KMMCOCRBusy; + TMMC::BigEndian4Bytes(cmd.iResponse, r3); + } + break; + + case ECmdAllSendCID: // CMD2 + { + TInt idx = FindAnyCardInStack(ECardStateReady); + + if (idx == -1) + rto = ETrue; + else + { + iCardInfo[idx]->iCID.Copy(cmd.iResponse); + iCardInfo[idx]->iState = ECardStateIdent; + } + } + break; + + case ECmdSetRelativeAddr: // CMD3 + { + TInt idx = FindOneCardInStack(ECardStateIdent); + iCardInfo[idx]->iRCA = tgtRCA; + iCardInfo[idx]->iState=ECardStateStby; + selCardIdx = idx; // set R1 response at end + } + break; + + case ECmdSelectCard: // CMD7 + { + // switch to broadcast mode so the currently selected and new cards + // receive the command simultaneously. + + TInt idx = FindAnyCardInStack(ECardStateTran); + if (idx != -1) + iCardInfo[idx]->iState = ECardStateStby; + iCardInfo[selCardIdx]->iState = ECardStateTran; + } + break; + + case ECmdSendStatus: + // R1 response so status return as for any other R1 command. + break; + + case ECmdReadSingleBlock: + case ECmdReadMultipleBlock: + { + winHandle=iCardInfo[selCardIdx]->iWinHandle; + + if ( cmd.iSpec.iUseStopTransmission && cmd.iBlockLength >= cmd.iTotalLength) + return( KMMCErrNotSupported ); + + TMMCErr err; + TInt pos = cmd.iArgument; + if (SetFilePointer(winHandle,pos,NULL,FILE_BEGIN)==0xffffffffu) + err=MapLastErrorMmc(); + else + { + iBytesToTransfer = cmd.BufferLength(); + err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection); + if(err == KMMCErrNone) + { + Session().RequestMoreData(); + SMF_WAITS(EStDoubleBuffer); + } + } + if (err!=KMMCErrNone) + return(err); + } + break; + + // ------------------------------------------------------------------ + case ECmdWriteBlock: + case ECmdWriteMultipleBlock: + { + HANDLE h = iCardInfo[selCardIdx]->iWinHandle; + + TMMCErr err; + TInt pos = cmd.iArgument; + if (SetFilePointer(h, pos, NULL, FILE_BEGIN)==0xffffffffu) + err = MapLastErrorMmc(); + else + { + iBytesToTransfer = cmd.BufferLength(); + err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection); + if(err == KMMCErrNone) + { + Session().RequestMoreData(); + SMF_WAITS(EStDoubleBuffer); + } + } + + if (err!=KMMCErrNone) + return(err); + } + break; + + case ECmdAppCmd: + rto = ETrue; + break; + + case ECmdSendCSD: + { + iCardInfo[selCardIdx]->GetCSD(cmd.iResponse); + break; + } + + // ------------------------------------------------------------------ + case ECmdLockUnlock: + // in EPOC, Lock() does not actually lock the card. It just sets the + // password. This means that the card is still accessible to the user, + // but must be unlocked the next time it is powered up. + + // a real card will transiently go into rcv and prg state while processing + // this command. When finished, it will fall back into tran state. + // The R1 response is sent immediately after CMD42. CIMReadWriteBlocksSM() + // sends CMD13 to find out whether or not LOCK_UNLOCK_FAIL was set. + + // the asserts in this case protect against invalid data being sent from the + // media driver. A real card would fail these corrupt data blocks. + + { +#ifdef __CARD0_NOT_LOCKABLE__ + if (*Wins::CurrentPBusDevicePtr() == 0) + return KMMCErrNotSupported; +#endif +#ifdef __CARD1_NOT_LOCKABLE__ + if (*Wins::CurrentPBusDevicePtr() == 1) + return KMMCErrNotSupported; +#endif + const TInt8 cmd_byte(*cmd.iDataMemoryP); + __ASSERT_DEBUG( // ensure not CLR_PWD && SET_PWD + !((cmd_byte & KMMCLockUnlockClrPwd) && (cmd_byte & KMMCLockUnlockSetPwd)), + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) ); + + __ASSERT_DEBUG( // ensure not FORCE_ERASE with CLR_PWD or SET_PWD + !((cmd_byte & KMMCLockUnlockErase) && (cmd_byte & (KMMCLockUnlockSetPwd | KMMCLockUnlockClrPwd))), + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) ); + + __ASSERT_DEBUG( // not actually lock a card while setting the password + ((cmd_byte & (KMMCLockUnlockLockUnlock | KMMCLockUnlockSetPwd)) != (KMMCLockUnlockLockUnlock | KMMCLockUnlockSetPwd)), + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCLockAttempt) ); + + if (cmd_byte & KMMCLockUnlockErase) // Forced Erase of a locked card + { + if (iCardInfo[selCardIdx]->iIsLocked) // Forced erase when locked + { + iCardInfo[selCardIdx]->iPWD->Zero(); // Remove the password + iCardInfo[selCardIdx]->iIsLocked = EFalse; + nextCMD42Failed = EFalse; + + TInt cardNum = (selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx; + SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD)); + + // Erase then entire contents of the emulated drive + HANDLE handle = iCardInfo[selCardIdx]->iWinHandle; + CloseHandle(handle); + iCardInfo[selCardIdx]->iWinHandle = NULL; + if(CreateBinFileForCard(selCardIdx, &handle, ETrue) != KErrNone) + return(MapLastErrorMmc()); + iCardInfo[selCardIdx]->iWinHandle = handle; + } + else // Forced erase when unlocked (illegal) + { + nextCMD42Failed = ETrue; + } + } + else + { + const TInt8 pwd_len = *(cmd.iDataMemoryP + 1); + const TPtrC8 pwd(cmd.iDataMemoryP + 2, pwd_len); + + if ((cmd_byte & KMMCLockUnlockClrPwd) != 0) // CLR_PWD == 1 + { + __ASSERT_DEBUG( + pwd_len >= 0 && pwd_len <= KMaxMediaPassword, + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand)); + + if (iCardInfo[selCardIdx]->iIsLocked) // clear when locked + nextCMD42Failed = ETrue; + else // clear when unlocked + { + if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0) // clear when unlocked with wrong password + { + nextCMD42Failed = ETrue; + lock_unlock_failed = ETrue; + } + else // clear when unlocked with right password + { + // Clear from password store + iCardInfo[selCardIdx]->iPWD->Zero(); + iCardInfo[selCardIdx]->iIsLocked = EFalse; + nextCMD42Failed = EFalse; + + // Clear from environment settings + TInt cardNum=(selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx; // Can't be -1 at this stage + SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD)); + } + } + } + else if ((cmd_byte & KMMCLockUnlockSetPwd) == 0) // SET_PWD == 0: unlock + { + __ASSERT_DEBUG( + pwd_len >= 0 && pwd_len <= KMaxMediaPassword, + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) ); + + if (! iCardInfo[selCardIdx]->iIsLocked) // unlock when unlocked + nextCMD42Failed = ETrue; + else + { + if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0) // unlock when locked with wrong password + { + nextCMD42Failed = ETrue; + lock_unlock_failed = ETrue; + } + else // unlock when locked with right password + { + iCardInfo[selCardIdx]->iIsLocked = EFalse; + nextCMD42Failed = EFalse; + } + } + } + else if ((cmd_byte & KMMCLockUnlockSetPwd) == KMMCLockUnlockSetPwd) // SET_PWD == 1 + { + __ASSERT_DEBUG( + cmd_byte & KMMCLockUnlockSetPwd, + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) ); + + // if pwd_len < iCardInfo[selCardIdx]->iPWD->Length() then data block must be invalid. + // This can be caused by bad user input rather than inaccurate formation. + if (!( pwd_len >= iCardInfo[selCardIdx]->iPWD->Length() + && pwd_len <= iCardInfo[selCardIdx]->iPWD->Length() + KMaxMediaPassword )) + { + nextCMD42Failed = ETrue; + } + else + { + TUint16 env_Var[]=L"_EPOC_PWD_LEN"; + TUint16 env_Val[2]; + TInt r=GetEnvironmentVariable(env_Var,&env_Val[0],2); + r=r;//This code is added to suppress WINS warnings + __ASSERT_DEBUG(r!=0,Kern::PanicCurrentThread(_L("PBUS-MMC-WINS-GETENV"),0)); + const TInt old_pwd_len=env_Val[0]-1; + TPtrC8 old_pwd(cmd.iDataMemoryP + 2, old_pwd_len); + TPtrC8 new_pwd(cmd.iDataMemoryP + 2 + old_pwd_len, pwd_len - old_pwd_len); + + // card must not be locked and supplied current password must be correct + if (iCardInfo[selCardIdx]->iIsLocked || iCardInfo[selCardIdx]->iPWD->Compare(old_pwd) != 0) + { + nextCMD42Failed = ETrue; + lock_unlock_failed = ETrue; + } + else + { + // Set in password store + iCardInfo[selCardIdx]->iPWD->Copy(new_pwd); + nextCMD42Failed = EFalse; + + // Set in environment settings + TInt cardNum=(selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx; // Can't be -1 at this stage + SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD)); + } + } + } + else if ((cmd_byte & KMMCLockUnlockLockUnlock) == KMMCLockUnlockLockUnlock) + { + __ASSERT_DEBUG( + pwd_len >= 0 && pwd_len <= KMaxMediaPassword, + DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) ); + + if (iCardInfo[selCardIdx]->iIsLocked) // lock when locked + nextCMD42Failed = ETrue; + else + { + if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0) // lock with wrong password + { + nextCMD42Failed = ETrue; + lock_unlock_failed = ETrue; + } + else // lock with right password + { + iCardInfo[selCardIdx]->iIsLocked = ETrue; + nextCMD42Failed = EFalse; + } + } + } + else + { + __ASSERT_DEBUG(EFalse, DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCLockAttempt) ); + } + } + } // case ECmdLockUnlock + break; + + case ECmdSetBlockCount: + { + // Only supported in version 3.1 + if(Session().iCardP->CSD().SpecVers() != 3) + { + return(KMMCErrNotSupported); + } + } + break; + + // ------------------------------------------------------------------ + default: + break; + } + + if (rto) + { + return(KMMCErrResponseTimeOut); + } + + // drop through to command done... + + SMF_STATE(EStCommandDone) + + cmd.iCommand = origCmd; + // If this is an R1 or R1b response type command then return card status as a response + if ( selCardIdx != KBroadcastToAllCards + && (cmd.iSpec.iResponseType==ERespTypeR1 || cmd.iSpec.iResponseType==ERespTypeR1B) ) + { + TUint32 resp( + iCardInfo[selCardIdx]->iState + | ((iCardInfo[selCardIdx]->iIsLocked ? 1 : 0) << 25) + | ((lock_unlock_failed ? 1 : 0) << 24) ); + + if (iCMD42Failed) // previous CMD42 + { + resp |= KMMCStatErrLockUnlock; + nextCMD42Failed = EFalse; + } + iCMD42Failed = nextCMD42Failed; + TMMC::BigEndian4Bytes(&cmd.iResponse[0],resp); // Ignore bits 47-40 + } + + SMF_GOTOS(EStEnd); + + SMF_STATE(EStDoubleBuffer) + + cmd.iBytesDone += iBytesToTransfer; + + if(cmd.iBytesDone < cmd.iTotalLength) + { + iBytesToTransfer = cmd.BufferLength(); + TMMCErr err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection); + if(err == KMMCErrNone) + { + Session().RequestMoreData(); + SMF_WAITS(EStDoubleBuffer); + } + else + { + return(err); + } + } + else + { + SMF_GOTOS(EStCommandDone); + } + + SMF_END + } + + +TMMCErr DWinsMMCStack::ReadWriteData(TInt aCardIdx, TUint8* aDataP, TUint32 aLength, TMMCCmdDirEnum aDir) + { + TMMCErr err = KMMCErrNone; + + HANDLE h = iCardInfo[aCardIdx]->iWinHandle; + + DWORD res; + TBool success; + + if(aDir == EDirWrite) + { + success = WriteFile(h, (LPCVOID)aDataP, aLength, &res, NULL); + } + else + { + success = ReadFile(h, (LPVOID)aDataP, aLength, &res, NULL); + } + + if (!success) + { + err=MapLastErrorMmc(); + } + else if (res != (DWORD)aLength) + { + err=KMMCErrGeneral; + } + + return(err); + } + + +TInt DWinsMMCStack::FindAnyCardInStack(TMMCardStateEnum aState) +// +// first first active card in supplied state. Return -1 if +// no active card is in supplied state. +// + { + for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i) + { + if (iCardInfo[i]->iState == aState) + return i; + } + return -1; + } + +TInt DWinsMMCStack::FindFirstCardInStack(TMMCardStateEnum aState) +// +// find card which is active on bus and in supplied state. +// There can be more than one active card in the the supplied state, +// but there should be at least one. +// + { + TInt idx = -1; + for (TInt i = 0; idx != -1 && i < TotalWinsMMC_CardSlots; ++i) + { + if (iCardInfo[i]->iState == aState) + idx = i; + } + + __ASSERT_DEBUG(idx != -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFFCNoneSel)); + return idx; + } + +TInt DWinsMMCStack::FindOneCardInStack(TMMCardStateEnum aState) +// +// find card which is active on bus and in supplied state. +// There should be exactly one active card in the supplied state. +// + { + TInt idx = -1; + for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i) + { + if (iCardInfo[i]->iState == aState) + { + __ASSERT_DEBUG(idx == -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFOCMultiSel)); + idx = i; + } + } + + __ASSERT_DEBUG(idx != -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFOCNoneSel)); + return idx; + } + +void DWinsMMCStack::SetupDiskParms(TUint aDiskSize) + { +// +// setup parms for emulated mmc disk size +// + // force a minimum of 32 KB total size + if (aDiskSize<32) + aDiskSize=32; + // first setup the CSD parameters + CSIZE_MULT = 0; + TUint newCSIZE = aDiskSize>>1; // with zero multiplier 1 + size parameter = size in KB / 2 + while((newCSIZE>0xfff)&&(CSIZE_MULT<7)) + // size parameter 12 bits, multiplier 3 bits + { + // size parameter too big and multiplier still has room to + // grow so increase multiplier and reduce size parameter + CSIZE_MULT++; + newCSIZE = aDiskSize>>(1+CSIZE_MULT); + } + CSIZE = newCSIZE; + // as CSIZE = 1 + CSIZE + CSIZE--; + // restrict to 12 bits + if (CSIZE>0xfff) + CSIZE=0xfff; + // now setup TotalDiskSize + TotalMDiskSize = 512 * (1+CSIZE) * (1<<(2+CSIZE_MULT)); + } + +// ======== TWinsMMCMediaChange ======== + +#pragma warning( disable : 4355 ) // this used in initializer list +DWinsMMCMediaChange::DWinsMMCMediaChange(TInt aMediaChangeNum) +// +// Constructor +// + : DMMCMediaChange(aMediaChangeNum), + iMediaChangeEnable(ETrue) + { + + iMediaDoorCloseReload=2; // Units: In theory-20ms, Actual-100ms + } +#pragma warning( default : 4355 ) + +TInt DWinsMMCMediaChange::Create() +// +// Initialiser. +// + { + return(DMediaChangeBase::Create()); + } + +void DWinsMMCMediaChange::DoorOpenService() +// +// Handle the media change (this function, never postponed is called on media +// change interrupt). +// + { + Disable(); // Disable interrupt until door closes again. + iDoorOpenDfc.Enque(); + } + +void DWinsMMCMediaChange::DoDoorOpen() +// +// Handle media door open (called on media door open interrupt). +// + { + iDoorClosedCount=iMediaDoorCloseReload; + // Just start a ticklink to poll for door closing + iTickLink.Periodic(KMediaChangeTickInterval,DWinsMMCMediaChange::Tick,this); + } + +void DWinsMMCMediaChange::DoDoorClosed() +// +// Handle media door closing +// + { + iTickLink.Cancel(); // Doesn't matter if wasn't enabled + Enable(); // Re-enable door interrupts + + // While the door was open the user may have changed the card in slot 0 + if (iStackP && *Wins::CurrentPBusDevicePtr() >= 0) + iStackP->iCardInfo[0]=iStackP->iCardPool[*Wins::CurrentPBusDevicePtr()]; + } + +void DWinsMMCMediaChange::ForceMediaChange() +// +// Force media change +// + { + DoorOpenService(); + } + +TMediaState DWinsMMCMediaChange::MediaState() +// +// Return status of media changed signal. +// + { + if (iDoorClosedCount>0) + return(EDoorOpen); + return( (*Wins::MediaDoorOpenPtr())?EDoorOpen:EDoorClosed); + } + +void DWinsMMCMediaChange::Tick(TAny *aPtr) +// +// Called on the tick to poll for door closing (called on DFC). +// + { + + ((DWinsMMCMediaChange*)aPtr)->TickService(); + } + +void DWinsMMCMediaChange::TickService() +// +// Called on the tick to poll for door closing (called on DFC). +// + { + + __ASSERT_DEBUG(iDoorClosedCount>=0,DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCMediaChangeTickFault)); + + if (!(*Wins::MediaDoorOpenPtr())) + { + if (iDoorClosedCount > 0) + { + if (--iDoorClosedCount == 0) + { + iTickLink.Cancel(); // cancel door closed timer + DoorClosedService(); + } + } + } + else + iDoorClosedCount=iMediaDoorCloseReload; // Door open so start again. + } + +void DWinsMMCMediaChange::Enable() +// +// Enable media change +// + { + + iMediaChangeEnable=ETrue; + } + +void DWinsMMCMediaChange::Disable() +// +// Disable media change +// + { + + iMediaChangeEnable=EFalse; + } + +void DWinsMMCMediaChange::MediaChangeCallBack(TAny *aPtr) +// +// Static called on media change +// + { + DWinsMMCMediaChange* mc=(DWinsMMCMediaChange*)aPtr; + if (mc!=NULL&&mc->iMediaChangeEnable) + mc->DoorOpenService(); + } + +// ======== TWinsCardInfo ======== + +void TWinsCardInfo::GetCSD(TUint8* aResp) const + { + // Bits 127-96 + TUint32 csd=(KCsdStructure<<30); /* CSD_STRUCTURE */ + csd|= (KCsdSpecVers<<26); /* SPEC_VERS */ + csd|= (0x0E<<16); /* TAAC: 1mS */ + csd|= (0x0A<<8); /* NSAC: 1000 */ + csd|= (0x59); /* TRAN_SPEED: 5.0Mbit/s */ + TMMC::BigEndian4Bytes(&aResp[0],csd); + + // Bits 95-64 + TUint32 lockBit = KMMCCmdClassLockCard; +#ifdef __CARD0_NOT_LOCKABLE__ + if (*Wins::CurrentPBusDevicePtr() == 0) + lockBit = 0; +#endif +#ifdef __CARD1_NOT_LOCKABLE__ + if (*Wins::CurrentPBusDevicePtr() == 1) + lockBit = 0; +#endif + const TUint32 ccc = + KMMCCmdClassBasic | KMMCCmdClassBlockRead + | KMMCCmdClassBlockWrite | lockBit; + csd= (ccc<<20); /* CCC: classes 0, 2, 4, and 7 */ + csd|= (0x9<<16); /* READ_BL_LEN: 512 bytes */ + csd|= (0x0<<15); /* READ_BL_PARTIAL: No */ + csd|= (0x0<<14); /* WRITE_BLK_MISALIGN: No */ + csd|= (0x0<<13); /* READ_BLK_MISALIGN: No */ + csd|= (0x0<<12); /* DSR_IMP: No DSR */ + csd|= ((DWinsMMCStack::CSIZE>>10&3)<<8); /* C_SIZE: MMCSz Kb */ + csd|= ((DWinsMMCStack::CSIZE>>2) & 0xFF); /* C_SIZE: MMCSz Kb */ + TMMC::BigEndian4Bytes(&aResp[4],csd); + // Bits 63-32 + csd= ((DWinsMMCStack::CSIZE&3)<<30); /* C_SIZE: MMCSz Kb */ + csd|= (0x1<<27); /* VDD_R_CURR_MIN: 1mA */ + csd|= (0x1<<24); /* VDD_R_CURR_MAX: 5mA */ + csd|= (0x2<<21); /* VDD_W_CURR_MIN: 5mA */ + csd|= (0x3<<18); /* VDD_W_CURR_MAX: 25mA */ + csd|= ((DWinsMMCStack::CSIZE_MULT&0x07)<<15); /* C_SIZE_MULT: 0 */ + csd|= (0x0<<10); /* SECTOR_SIZE: 1 write block */ + csd|= (0x0<<5); /* ERASE_GRP_SIZE: 1 secotr */ + csd|= (0x0); /* WP_GRP_SIZE: 1 erase group */ + TMMC::BigEndian4Bytes(&aResp[8],csd); + // Bits 31-0 + csd= (0x0<<31); /* WP_GRP_ENABLE: No */ + csd|= (0x0<<29); /* DEFAULT_ECC: ? */ + csd|= (0x3<<26); /* R2W_FACTOR: 8 */ + csd|= (0x9<<22); /* WRITE_BL_LEN: 512 bytes */ + csd|= (0x0<<21); /* WRITE_BL_PARTIAL: No */ + csd|= (0x0<<15); /* FILE_FORMAT_GRP: Hard disk */ + csd|= (0x0<<14); /* COPY: original */ + csd|= (0x0<<13); /* PERM_WRITE_PROTECT: No */ + csd|= (0x0<<12); /* TMP_WRITE_PROTECT: No */ + csd|= (0x0<<10); /* FILE_FORMAT: Hard disk */ + csd|= (0x0<<8); /* ECC: None */ + csd|= (0x0<<1); /* CRC: ? */ + csd|= (0x1); /* not used */ + TMMC::BigEndian4Bytes(&aResp[12],csd); + } + +// ======== TWinsMMCPsu ======== + + +DWinsMMCPsu::DWinsMMCPsu(TInt aVccNum, TInt aMcId) +// +// Constructor. +// + : DMMCPsu(aVccNum, aMcId) + {} + +TInt DWinsMMCPsu::DoCreate() +// +// Initialise the PSU +// + { + // Nothing to do + return KErrNone; + } + +void DWinsMMCPsu::DoSetState(TPBusPsuState aState) +// +// Turn on/off the PSU. If it is possible to adjust the output voltage on this +// PSU then retreive the required voltage level from TMMCPsu::iVoltageSetting +// (which is in OCR register format). +// + { + + switch (aState) + { + case EPsuOff: + break; + case EPsuOnFull: + break; + case EPsuOnCurLimit: + break; + } + } + +TInt DWinsMMCPsu::VoltageInMilliVolts() +// +// Return the level of the PSU (in mV) or -ve if error. +// + { + + return(0); + } + +void DWinsMMCPsu::DoCheckVoltage() +// +// Check the voltage level of the PSU is as expected. Returns either KErrNone, KErrGeneral +// to indicate the pass/fail state or KErrNotReady if the voltage check isn't complete. +// + { + ReceiveVoltageCheckResult(KErrNone); + } + +void DWinsMMCPsu::PsuInfo(TPBusPsuInfo &anInfo) +// +// Return machine info relating to the MMC PSU supply +// + { + + anInfo.iVoltageSupported=0x00040000; // 3.0V (OCR reg. format). + anInfo.iMaxCurrentInMicroAmps=0; + anInfo.iVoltCheckInterval=0; + anInfo.iVoltCheckMethod=EPsuChkComparator; + anInfo.iNotLockedTimeOut=0; + anInfo.iInactivityTimeOut=5; + } + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/mmci.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/mmci.h Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,167 @@ +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// PP_MMC.H +// +// + +#ifndef __PP_MMC_H__ + +#if defined(_UNICODE) && !defined(UNICODE) + #define UNICODE +#endif + +#include +#include + +// MultiMedia Card Controller - platform specific layer. + +GLREF_C TInt MapLastErrorEpoc(); +GLREF_C TMMCErr MapLastErrorMmc(); + +const TInt KMediaChangeTickInterval=20000; // Units 1uS + + +const TInt KMax_TotalWinsCardSlots=8; ///< Maximal number of MMC cards supported by the emulator +const TInt KMax_TotalWinsCards=(KMax_TotalWinsCardSlots+1); ///< Maximal number of MMC slots, supported by the emulator. Need 2 cards for slot 0 + +const TInt KDefault_TotalWinsCardSlots=2; ///< Default number of MMC cards supported by the emulator +const TInt KDefault_TotalWinsCards=(KDefault_TotalWinsCardSlots+1); ///< Default number of MMC slots, supported by the emulator. Need 2 cards for slot 0 + + +const TUint32 KMMCWinsCardOCRValue = 0x00FFFF00; + +class TWinsCardInfo + { +public: + void GetCSD(TUint8* aResp) const; +public: + TCID iCID; + TMediaPassword* iPWD; // PWD_LEN calculated from PWD. + TBool iIsLocked; // Could use iCurrentCardIsLocked + TMMCardStateEnum iState; // Simulation of card's current state + HANDLE iWinHandle; + TRCA iRCA; + }; + +class DWinsMMCStack : public DMMCStack + { +private: + DWinsMMCStack(TInt aBus, DMMCSocket* aSocket); + TInt Init(); +private: + virtual void MachineInfo(TMMCMachineInfo& aMachineInfo); +public: + virtual void AdjustPartialRead(const TMMCard* aCard, TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd) const; + virtual void GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen); + + enum TWinsMMCPanic + { + EWinsMMCLidOpenIntBind=0, + EWinsMMCBadMachineInfo=1, + EWinsMMCMediaChangeTickFault = 2, + EWinsMMCCorruptCommand = 3, + EWinsMMCLockAttempt = 4, + EWinsMMCAPRNotSupp = 5, + EWinsMMCAPRRange = 6, + EWinsMMCAPRBoundary = 7, + + EStkFFCNotSelCard = 0x010, EStkFFCNoneSel, + EStkFOCNotSelCard = 0x011, EStkFOCMultiSel, EStkFOCNoneSel + }; + + static TInt TotalMDiskSize; // mmc card size for emulator + static TUint CSIZE; // mmc card size field + static TUint CSIZE_MULT; // mmc card size field + + static TInt TotalWinsMMC_CardSlots; // total number of MMC card slots for the emulator + static TInt TotalWinsMMC_Cards; // total number of MMC cards for the emulator + + static void Panic(TWinsMMCPanic aPanic); + +private: + TUint8* iMDBuf; + TInt iMDBufLen; + +private: + // Stack service provided by ASSP layer + void SetBusConfigDefaults(TMMCBusConfig&, TUint aClock); + void InitClockOff(); + void ASSPReset(); + void ASSPDisengage(); + void DoPowerDown(); + // State Machine functions implemented in ASSP layer + TMMCErr DoPowerUpSM(); + TMMCErr InitClockOnSM(); + TMMCErr IssueMMCCommandSM(); + TMMCErr ModifyCardCapabilitySM(); +private: + TInt SetupSimulatedCard(TInt aCardNum); // init + TInt CreateBinFileForCard(TInt aCardNum, HANDLE* aHandle, TBool aCreateNew = EFalse); + TInt GetTargetSlotNumber(TBool anRCASupplied, const TRCA& anRCA); + TInt FindAnyCardInStack(TMMCardStateEnum aState); + TInt FindFirstCardInStack(TMMCardStateEnum aState); + TInt FindOneCardInStack(TMMCardStateEnum aState); + void SetupDiskParms(TUint); + TMMCErr ReadWriteData(TInt aCardIdx, TUint8* aDataP, TUint32 aLength, TMMCCmdDirEnum aDir); +private: + TWinsCardInfo* iCardPool[KMax_TotalWinsCards]; // All the cards created + TWinsCardInfo* iCardInfo[KMax_TotalWinsCardSlots]; // Cards currently present (1 per slot) + TBool iCMD42Failed; + TUint32 iBytesToTransfer; + friend class DWinsMMCMediaChange; + friend class TMMCardControllerInterfaceWins; + }; + +class DWinsMMCStack; +class DWinsMMCMediaChange : public DMMCMediaChange + { +public: + DWinsMMCMediaChange(TInt aMediaChangeNum); + virtual TInt Create(); + virtual void ForceMediaChange(); + virtual void DoDoorOpen(); + virtual void DoDoorClosed(); + virtual TMediaState MediaState(); + inline void SetStackP(DWinsMMCStack* aStackP) {iStackP=aStackP;} +protected: + void DoorOpenService(); +private: + static void Tick(TAny *aPtr); + void TickService(); + void Enable(); + void Disable(); + static void MediaChangeCallBack(TAny *aPtr); + static void MediaChangeDFC(TAny* aPtr); +private: + TTickLink iTickLink; + TInt iDoorClosedCount; + TBool iMediaChangeEnable; + TInt iMediaDoorCloseReload; // Units: In theory-20ms, Actual-100ms + DWinsMMCStack* iStackP; + friend class DWinsMMCStack; + }; + +class DWinsMMCPsu : public DMMCPsu + { +public: + DWinsMMCPsu(TInt aVccNum, TInt aMcId); + virtual TInt DoCreate(); + virtual void DoSetState(TPBusPsuState aState); + virtual TInt VoltageInMilliVolts(); +private: + virtual void DoCheckVoltage(); + virtual void PsuInfo(TPBusPsuInfo &anInfo); + }; + +#endif // #ifndef __PP_MMC_H__ diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/mmcv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/mmcv.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,135 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\mmcv.cpp +// WINS variant +// +// + +#include +#include "mmci.h" +#include "variantmediadef.h" + +// +// Factory class for creation of platform specifics +// +class TMMCardControllerInterfaceWins : public TMMCardControllerInterface + { + // Factory functions + virtual DMMCSocket* NewSocket(TInt aSocketNum, TMMCPasswordStore* aPasswordStore); + virtual DMMCStack* NewStack(TInt aStackNum, DMMCSocket* aSocket); + virtual DMMCMediaChange* NewMediaChange(TInt aMcId); + virtual DMMCPsu* NewVcc(TInt aVccNum, TInt aMcId); + // Stack initialisation + virtual TInt Init(); + // Machine configuration + virtual TBool IsMMCSocket(TInt aSocket,SMediaDeviceInfo& aMediaDeviceInfo); + virtual TInt MediaChangeID(TInt aSocket); + virtual TInt VccID(TInt aSocket); + }; + + +TInt TMMCardControllerInterfaceWins::Init() +// +// Initialise the Controller h/w +// + { + return KErrNone; + } + +TInt TMMCardControllerInterfaceWins::MediaChangeID(TInt aSocket) +// +// Return the socket's media change index +// + { + return aSocket; + } + +TInt TMMCardControllerInterfaceWins::VccID(TInt aSocket) +// +// Return the socket's PSU index +// + { + return aSocket; + } + +static const TInt DriveNumbers[MMC0_DRIVECOUNT]={MMC0_DRIVELIST}; +_LIT(KLitMmcSocketName,MMC0_DRIVENAME); +TBool TMMCardControllerInterfaceWins::IsMMCSocket(TInt aSocket,SMediaDeviceInfo& aMediaDeviceInfo) +// +// Confirm whether an MMC stack is supported on the specified +// socket and if it is, the Media Info. for that socket. +// + { + + if (aSocket==0) + { + aMediaDeviceInfo.iDevice=MEDIA_DEVICE_MMC; + aMediaDeviceInfo.iDriveCount=MMC0_DRIVECOUNT; + aMediaDeviceInfo.iDriveList=&DriveNumbers[0]; + aMediaDeviceInfo.iNumMedia=MMC0_NUMMEDIA; + aMediaDeviceInfo.iDeviceName=&KLitMmcSocketName; + return(ETrue); + } + else + return(EFalse); + } + +DMMCSocket* TMMCardControllerInterfaceWins::NewSocket(TInt aSocketNum, TMMCPasswordStore* aPasswordStore) +// +// Create a new platform-specific socket +// + { + return new DMMCSocket(aSocketNum, aPasswordStore); + } + +DMMCStack* TMMCardControllerInterfaceWins::NewStack(TInt aStackNum, DMMCSocket* aSocket) +// +// Create a new platform-specific stack +// + { + return new DWinsMMCStack(aStackNum, aSocket); + } + +DMMCMediaChange* TMMCardControllerInterfaceWins::NewMediaChange(TInt aMcId) +// +// Create a new platform-specific media change +// + { + return new DWinsMMCMediaChange(aMcId); + } + +DMMCPsu* TMMCardControllerInterfaceWins::NewVcc(TInt aVccNum, TInt aMcId) +// +// Create a new platform-specific PSU +// + { + return new DWinsMMCPsu(aVccNum, aMcId); + } + +DECLARE_STANDARD_EXTENSION() +// +// Extension Entry Point +// + { + __KTRACE_OPT(KPBUS1,Kern::Printf("Starting MMC interface")); + + TInt r=KErrNoMemory; + TMMCardControllerInterfaceWins* pI=new TMMCardControllerInterfaceWins; + if (pI) + r=pI->Create(); + + __KTRACE_OPT(KPBUS1,Kern::Printf("Returns %d",r)); + return r; + } + diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/multitouch.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/multitouch.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,522 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// wins\specific\multitouch.cpp +// +// +#include "multitouch.h" +#include "resource.h" + +#define KDefaultMaxProximity -100 +#define KDefaultMaxPressure 5000 +#define KDefaultPressureStep 500 +#define KDefaultProximityStep 5 + +// Static members +DMultiMouse DMultiMouse::iMice[KMaxMice]; +int DMultiMouse::iNumMice = 0; +DMultiMouse* DMultiMouse::iPrimary = 0; +int DMultiMouse::iMouseId = 0; +int DMultiTouch::iNumberOfMice = 0; +bool DMultiTouch::iMultiTouchSupported= FALSE; +bool DMultiTouch::iMultiTouchCreated= FALSE; +bool DMultiTouch::iMultiTouchTempEnabled= FALSE; + +// Function pointers for raw input APIs +TYPEOF_RegisterRawInputDevices pfnRegisterRawInputDevices= NULL; +TYPEOF_GetRawInputData pfnGetRawInputData= NULL; +TYPEOF_GetRawInputDeviceList pfnGetRawInputDeviceList=NULL; + +/** + * Initialise the proximity and pressure information if undefined by the user + */ +DMultiTouch::DMultiTouch(TInt aProximityStep, TInt aPressureStep) + { + iZMaxRange = KDefaultMaxProximity; + iMaxPressure = KDefaultMaxPressure; + iProximityStep = (aProximityStep == -1) ? KDefaultProximityStep : aProximityStep; + iPressureStep = (aPressureStep == -1) ? KDefaultPressureStep : aPressureStep; + } + +/** + * Register all the mice +*/ +BOOL DMultiTouch::Register() + { + RAWINPUTDEVICE device; + device.usUsagePage = 0x01; + device.usUsage = 0x02; + device.dwFlags = RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages + device.hwndTarget = 0; + ShowCursors(); + return pfnRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE)); + } + +/** + * Unregister mice devices + */ +BOOL DMultiTouch::UnRegister() + { + RAWINPUTDEVICE device; + device.usUsagePage = 0x01; + device.usUsage = 0x02; + device.dwFlags = RIDEV_REMOVE; + device.hwndTarget = NULL; + HideCursors(); + return pfnRegisterRawInputDevices(&device, 1, sizeof(RAWINPUTDEVICE)); + } + + +/* * Handle multi-input Window messages + */ +void DMultiTouch::OnWmInput(HWND aHWnd,TUint aMessage,TUint aWParam,TUint aLParam,HWND aParentHwnd) + { + RAWINPUT ri; + UINT dwSize = sizeof(ri); + if (pfnGetRawInputData((HRAWINPUT)aLParam, RID_INPUT, &ri, &dwSize, sizeof(RAWINPUTHEADER))==(UINT)-1) + { + OutputDebugString(TEXT("GetRawInputData has an error !\n")); + } + else if (ri.header.dwType == RIM_TYPEMOUSE) + { + DMultiMouse* mouse = DMultiMouse::Find(ri.header.hDevice); + if (mouse) + { + if (!DMultiMouse::iPrimary) + { + DMultiMouse::iPrimary = mouse; + DMultiMouse::iPrimary->iIsPrimary = TRUE; + } + mouse->HandleRawMouseEvent(ri.data.mouse, aParentHwnd); + } + } + DefWindowProcA(aHWnd, aMessage, aWParam, aLParam); + } + +void DMultiTouch::HideCursors() + { + for (int ii=0; iiiCursor,0,0,0,NULL, DI_NORMAL | DI_DEFAULTSIZE); + EndPaint(hwnd, &ps); + return 0; + } + return DefWindowProc(hwnd, msg, wp, lp); + } + +CursorWindow::CursorWindow(): iHwnd(NULL),iCursor(NULL),iNumber(0) + { + } + +HWND CursorWindow::Create(HMODULE hm, HWND hwndParent, int number) + { + // Create the window + static ATOM atom = NULL; + if (!atom) + { + WNDCLASSEX wcex; + ZeroMemory(&wcex, sizeof(wcex)); + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_OWNDC; + wcex.lpfnWndProc = (WNDPROC)CursorWndProc; + wcex.hInstance = (HINSTANCE)hm; + wcex.lpszClassName = TEXT("CursorWndClass"); + wcex.hbrBackground = CreateSolidBrush(RGB(255,0,0));//Background color is also for the number + atom = RegisterClassEx(&wcex); + } + iHwnd = CreateWindowA((LPCSTR)atom, NULL, WS_CHILD|WS_CLIPSIBLINGS, 0,0,64,64, hwndParent, NULL, hm, NULL); + SetWindowLong(iHwnd, GWL_USERDATA, (LONG)this); + iNumber = number; + return iHwnd; + } + +void CursorWindow::Show() + { + ShowWindow(iHwnd, SW_NORMAL); + } + +void CursorWindow::Hide() + { + ShowWindow(iHwnd, SW_HIDE); + } + +BOOL CursorWindow::SetCursor(HCURSOR hc) + { + // Duplicate the cursor (because we're going to draw a number on the mask) + if (iCursor) + { + DestroyCursor(iCursor); + iCursor = NULL; + } + iCursor = CopyCursor(hc); + + // Get information about the cursor, and select its mask bitmap into a temporary DC. + ICONINFO ii; + GetIconInfo(iCursor, &ii); + iHotspot.x = ii.xHotspot; + iHotspot.y = ii.yHotspot; + HDC hdc = CreateCompatibleDC(NULL); + SelectObject(hdc, ii.hbmMask); + + // Get the cursor's pixel size + BITMAPINFO bmi; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biBitCount = 0; + GetDIBits(hdc, ii.hbmMask, 0, 0, NULL, &bmi, DIB_RGB_COLORS); + int cx = bmi.bmiHeader.biWidth; + int cy = bmi.bmiHeader.biHeight; + + // Monochrome cursors have a double-height hbmMask. The top half contains the AND + // bitmap (which we do want) and the bottom half contains the XOR bitmap (which we + // dont want). Colour cursors have a single normal-height AND mask. + BOOL isMonochrome = (ii.hbmColor==NULL); + int cyy = isMonochrome ? (cy>>1) : cy; + + // Draw the number into the mask + char ach[4]; + int ld = iNumber/10; + int rd = iNumber % 10; + if (ld > 0) + { + wsprintf((LPTSTR)ach, (LPCTSTR)TEXT("%d%d"), ld,rd); + } + else + { + wsprintf((LPTSTR)ach, (LPCTSTR)TEXT("%d"), rd); + } + + HFONT hf = CreateFontA(12,0, 0,0,FW_THIN, FALSE,FALSE,FALSE, 0,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, "Arial"); + SelectObject(hdc, hf); + SetBkMode(hdc, TRANSPARENT); + TextOutA(hdc, 0,cyy-12, ach, 2); + DeleteObject(hf); + + // Get the bits of the mask (in 32-bit colour) + HANDLE heap = GetProcessHeap(); + bmi.bmiHeader.biBitCount = 32; + DWORD* bits = (DWORD*)HeapAlloc(heap, 0, cx*cy*4); + GetDIBits(hdc, ii.hbmMask, 0, cy, bits, &bmi, DIB_RGB_COLORS); + + // Set the window to the size of the cursor + SetWindowPos(iHwnd, NULL,0,0,cx,cyy, SWP_NOMOVE); + + // Create a cursor-shaped region by starting out with an empty region + // and ORing in each zero-valued mask pixel. + HRGN rgn = CreateRectRgn(0,0,0,0); + for (int y=0 ; yiX; + iY = iPrimary->iY; + } + + if (aEvent.usFlags & MOUSE_MOVE_ABSOLUTE) + { + // absolute position info can update all pointers + iX = aEvent.lLastX; + iY = aEvent.lLastY; + } + else if (!iIsPrimary) + { + // relative position info updates non-primary pointers, + iX += aEvent.lLastX; + iY += aEvent.lLastY; + } + + // Show the cursor window + ShowMousePos(aWnd); + + TInt message = WM_MOUSEMOVE; + + // get button state + if (aEvent.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) + { + message = WM_LBUTTONDOWN; + iZ = 0; + } + + if (aEvent.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) + { + message = WM_LBUTTONUP; + iZ = 0; + } + + if (aEvent.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) + { + message = WM_RBUTTONDOWN; + } + + if (aEvent.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) + { + message = WM_RBUTTONUP; + } + + if (aEvent.usButtonFlags & RI_MOUSE_WHEEL) + { + message = WM_MOUSEWHEEL; + if ((TInt16)(aEvent.usButtonData&0x8000)== 0) // positive number + { + if (iZ < TheMultiTouch->iMaxPressure) + { + if (iZ>=0) + { // pressure range + iZ += TheMultiTouch->iPressureStep;//Pressure step + if (iZ > TheMultiTouch->iMaxPressure) + { + iZ = TheMultiTouch->iMaxPressure; + } + } + else + { // proximity range + iZ += TheMultiTouch->iProximityStep; //Proximity step + } + } + } + else + { + if (iZ > TheMultiTouch->iZMaxRange) + { + if (iZ <= 0) + {// proximity range + iZ -= TheMultiTouch->iProximityStep;//Proximity step + if (iZ < TheMultiTouch->iZMaxRange) + { + iZ = TheMultiTouch->iZMaxRange; + } + } + else + {// pressure range + iZ -= TheMultiTouch->iPressureStep;//Pressure step + } + } + } + } + + MultiTouchWndPointer(message, iX, iY, iZ, iId); + + } + +/** + * Show the cursor window when the cursor is inside the client area + */ +void DMultiMouse::ShowMousePos(HWND aHWnd) + { + RECT client = {0,0,0,0}; + if(aHWnd) + { + GetWindowRect(aHWnd, &client); + POINT pt = {iX-client.left,iY-client.top}; + iCursorWnd.SetPosition(pt); + } + iCursorWnd.Show(); + } + +void DMultiMouse::CorrectSystemMouse() + { + if (iIsPrimary) + { + POINT pos; + if (GetCursorPos(&pos)) // if failed, pos contains garbage. + { + iX = pos.x; + iY = pos.y; + } + } + else + { + SetCursorPos(iPrimary->iX,iPrimary->iY); + } + } + +/** + * a static function to check how many mice are connected +*/ +bool DMultiTouch::Init() + { + HMODULE hModule = GetModuleHandleA("user32.dll"); + if(hModule == NULL) + return FALSE; + + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + // Check for Win 2K or higher version + if (osvi.dwMajorVersion < 5) + { + return FALSE; + } + + // Not supported on Win2K + if ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 0)) + { + return FALSE; + } + + pfnRegisterRawInputDevices = (TYPEOF_RegisterRawInputDevices)GetProcAddress(hModule, "RegisterRawInputDevices"); + pfnGetRawInputData = (TYPEOF_GetRawInputData)GetProcAddress(hModule, "GetRawInputData"); + pfnGetRawInputDeviceList = (TYPEOF_GetRawInputDeviceList)GetProcAddress(hModule, "GetRawInputDeviceList"); + + if((pfnRegisterRawInputDevices == NULL) || (pfnGetRawInputData == NULL) || (pfnGetRawInputDeviceList == NULL)) + { + return FALSE; + } + + UINT nDevices; + + if (pfnGetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0) + { + return FALSE; + } + + RAWINPUTDEVICELIST* pRawInputDeviceList = new RAWINPUTDEVICELIST[ nDevices ]; + if (!pRawInputDeviceList) + { + return FALSE; + } + + pfnGetRawInputDeviceList(pRawInputDeviceList, &nDevices, + sizeof(RAWINPUTDEVICELIST)); + + + for (UINT i=0; i