Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.
// 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 the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// template\template_variant\specific\keyboard.cpp
// Access to Template interruptible keyboard
// The code here implements a simple interrupt-driven keyboard driver.
// This is an alternative to the polled driver in keyboard.cpp.
// This example assumes that we have an intelligent keyboard controller
// which:
// scans the keyboard automatically
// generates an interrupt when a key is pressed or released
// You can use this code as a starting point and modify it to suit
// your hardware.
//
//
#include <template_assp.h>
#include "iolines.h"
#include "platform.h"
#include <kernel/kpower.h>
#include <e32keys.h>
//
//
// TO DO: (optional)
//
// Modify this conversion table to suit your keyboard layout
//
// This example assumes that the following keyboard layout:
//
// <----Row0-----><-----Row1-------><---Row2-----><-----Row3-------><-------Row4-----------><------Row5------><-----Row6-------><---Row7--->
// LAlt Column0
// ' \ TAB Z A X Column1
// LShift Column2
// LCtrl Column3
// Fn Column4
// Esc Del Q CapLk S C 3 Column5
// 1 W D V 4 Column6
// 2 T E F B 5 Column7
// 9 Y R K G N 6 Column8
// 0 U O L H M 7 Column9
// - I P ; J , 8 Column10
// = Enter [ ' / . Prog Column11
// RShift Column12
// BkSp DnArrow ] UpArrow LeftArrow Space RightArrow Column13
// Column14
// Column15
// EXAMPLE ONLY
const TUint8 convertCode[] =
{
EStdKeyNull , EStdKeyLeftAlt , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column0
EStdKeyNull , EStdKeyHash ,EStdKeyBackSlash, EStdKeyTab , 'Z' , 'A' , 'X' ,EStdKeyNull, // Column1
EStdKeyNull , EStdKeyNull ,EStdKeyLeftShift, EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column2
EStdKeyNull , EStdKeyLeftCtrl , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column3
EStdKeyNull , EStdKeyLeftFunc , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column4
EStdKeyNull , EStdKeyEscape , EStdKeyDelete , 'Q' , EStdKeyCapsLock , 'S' , 'C' , '3' , // Column5
EStdKeyNull , '1' , EStdKeyNull , 'W' , EStdKeyNull , 'D' , 'V' , '4' , // Column6
EStdKeyNull , '2' , 'T' , 'E' , EStdKeyNull , 'F' , 'B' , '5' , // Column7
EStdKeyNull , '9' , 'Y' , 'R' , 'K' , 'G' , 'N' , '6' , // Column8
EStdKeyNull , '0' , 'U' , 'O' , 'L' , 'H' , 'M' , '7' , // Column9
EStdKeyNull , EStdKeyMinus , 'I' , 'P' , EStdKeySemiColon , 'J' , EStdKeyComma , '8' , // Column10
EStdKeyNull , EStdKeyEquals , EStdKeyEnter ,EStdKeySquareBracketLeft,EStdKeySingleQuote,EStdKeyForwardSlash, EStdKeyFullStop ,EStdKeyMenu, // Column11
EStdKeyNull , EStdKeyNull ,EStdKeyRightShift, EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column12
EStdKeyNull , EStdKeyBackspace ,EStdKeyDownArrow,EStdKeySquareBracketRight,EStdKeyUpArrow , EStdKeyLeftArrow , EStdKeySpace ,EStdKeyRightArrow, // Column13
EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull, // Column14
EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,EStdKeyNull // Column15
};
// EXAMPLE ONLY
const TInt KFlagKeyPressed = 0x80; // As an example, we'll assume the top bit indicates pressed/released
// EXAMPLE ONLY
const TKeyboard KConfigKeyboardType = EKeyboard_Full;
const TInt KConfigKeyboardDeviceKeys = 0;
const TInt KConfigKeyboardAppsKeys = 0;
//
//
_LIT(KLitKeyboard,"Keyboard");
class DKeyboardTemplate : public DPowerHandler
{
public:
DKeyboardTemplate();
TInt Create();
public: // from DPowerHandler
void PowerUp();
void PowerDown(TPowerState);
TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
void KeyboardInfo(TKeyboardInfoV01& aInfo);
void KeyboardOn();
void KeyboardOff();
void HandleMsg(TMessageBase* aMsg);
private:
static void Isr(TAny* aPtr);
static void EventDfcFn(TAny* aPtr);
void EventDfc();
void PowerUpDfc();
static void PowerUpDfcFn(TAny* aPtr);
void PowerDownDfc();
static void PowerDownDfcFn(TAny* aPtr);
private:
void KeyboardPowerUp();
TUint GetKeyCode();
TBool IsKeyReady();
public:
TDfcQue* iDfcQ;
TMessageQue iMsgQ;
TDfc iPowerUpDfc;
TDfc iPowerDownDfc;
private:
TDfc iEventDfc;
TBool iKeyboardOn;
};
LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
{
DKeyboardTemplate* pH=(DKeyboardTemplate*)aPtr;
return pH->HalFunction(aFunction,a1,a2);
}
void rxMsg(TAny* aPtr)
{
DKeyboardTemplate& h=*(DKeyboardTemplate*)aPtr;
TMessageBase* pM=h.iMsgQ.iMessage;
if (pM)
h.HandleMsg(pM);
}
//
// Keyboard class
//
DKeyboardTemplate::DKeyboardTemplate()
: DPowerHandler(KLitKeyboard),
iMsgQ(rxMsg,this,NULL,1),
iPowerUpDfc(PowerUpDfcFn,this,6),
iPowerDownDfc(PowerDownDfcFn,this,7),
iEventDfc(EventDfcFn,this,1)
{
}
TInt DKeyboardTemplate::Create()
//
// Initialisation. Bind and enable the interrupt.
//
{
iDfcQ=Kern::DfcQue0();
iKeyboardOn = EFalse;
// install the HAL function
TInt r=Kern::AddHalEntry(EHalGroupKeyboard,halFunction,this);
if (r!=KErrNone)
return r;
iEventDfc.SetDfcQ(iDfcQ);
iPowerUpDfc.SetDfcQ(iDfcQ);
iPowerDownDfc.SetDfcQ(iDfcQ);
iMsgQ.SetDfcQ(iDfcQ);
iMsgQ.Receive();
// Bind the key event interrupt
r=Interrupt::Bind(KIntIdKeyboard,Isr,this);
if (r==KErrNone)
{
// install the power handler
Add();
KeyboardPowerUp();
}
return r;
}
void DKeyboardTemplate::Isr(TAny* aPtr)
{
DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr;
Interrupt::Disable(KIntIdKeyboard);
k.iEventDfc.Add();
}
void DKeyboardTemplate::EventDfcFn(TAny* aPtr)
{
((DKeyboardTemplate*)aPtr)->EventDfc();
}
void DKeyboardTemplate::EventDfc()
{
__KTRACE_OPT(KHARDWARE,Kern::Printf("DKeyboardTemplate::EventDfc"));
TInt irq=NKern::DisableAllInterrupts();
while (IsKeyReady()) // while there are keys in the controller's output buffer
{
NKern::RestoreInterrupts(irq);
TRawEvent e;
TUint keyCode=GetKeyCode(); // Read keycodes from controller
__KTRACE_OPT(KHARDWARE,Kern::Printf("#%02x",keyCode));
//
// TO DO: (mandatory)
//
// Convert from hardware scancode to EPOC scancode and send the scancode as an event (key pressed or released)
// as per below EXAMPLE ONLY:
//
TUint bareCode=keyCode&~KFlagKeyPressed;
TUint8 stdKey=convertCode[bareCode];
if (keyCode&KFlagKeyPressed)
e.Set(TRawEvent::EKeyUp,stdKey,0);
else
e.Set(TRawEvent::EKeyDown,stdKey,0);
Kern::AddEvent(e);
NKern::Sleep(1); // pause before reading more keycodes
irq=NKern::DisableAllInterrupts();
}
Interrupt::Enable(KIntIdKeyboard);
NKern::RestoreInterrupts(irq);
}
TBool DKeyboardTemplate::IsKeyReady()
{
//
// TO DO: (mandatory)
//
// Return ETrue if the keyboard controller has a key event waiting to be read
//
return EFalse; // EXAMPLE ONLY
}
TUint DKeyboardTemplate::GetKeyCode()
{
//
// TO DO: (mandatory)
//
// Read and return the next available keycode from the keyboard controller
//
return 0; // EXAMPLE ONLY
}
void DKeyboardTemplate::PowerUpDfcFn(TAny* aPtr)
{
((DKeyboardTemplate*)aPtr)->PowerUpDfc();
}
void DKeyboardTemplate::PowerDownDfcFn(TAny* aPtr)
{
((DKeyboardTemplate*)aPtr)->PowerDownDfc();
}
void DKeyboardTemplate::KeyboardPowerUp()
{
__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardPowerUp()"));
iKeyboardOn = ETrue;
// Send key up events for EStdKeyOff (Fn+Esc) event
TRawEvent e;
e.Set(TRawEvent::EKeyUp,EStdKeyEscape,0);
Kern::AddEvent(e);
e.Set(TRawEvent::EKeyUp,EStdKeyLeftFunc,0);
Kern::AddEvent(e);
}
void DKeyboardTemplate::PowerUp()
{
iPowerUpDfc.Enque(); // schedules DFC to execute on this driver's thread
}
void DKeyboardTemplate::PowerUpDfc()
{
__KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerUpDfc()"));
KeyboardOn();
PowerUpDone(); // must be called from a different thread than PowerUp()
}
void DKeyboardTemplate::KeyboardOn()
{
__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOn() iKeyboardOn=%d", iKeyboardOn));
if (!iKeyboardOn) // may be powered up from Power Manager or HAL
{
KeyboardPowerUp();
}
}
void DKeyboardTemplate::PowerDown(TPowerState)
{
iPowerDownDfc.Enque(); // schedules DFC to execute on this driver's thread
}
void DKeyboardTemplate::PowerDownDfc()
{
__KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerDownDfc()"));
KeyboardOff();
PowerDownDone(); // must be called from a different thread than PowerDown()
}
void DKeyboardTemplate::KeyboardOff()
{
__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOff() iKeyboardOn=%d", iKeyboardOn));
if (iKeyboardOn) // may have already been powered down by the HAL
{
iKeyboardOn = EFalse;
Interrupt::Disable(KIntIdKeyboard);
}
iEventDfc.Cancel();
}
void DKeyboardTemplate::HandleMsg(TMessageBase* aMsg)
{
if (aMsg->iValue)
KeyboardOn();
else
KeyboardOff();
aMsg->Complete(KErrNone,ETrue);
}
void DKeyboardTemplate::KeyboardInfo(TKeyboardInfoV01& aInfo)
{
__KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::KeyboardInfo"));
aInfo.iKeyboardType=KConfigKeyboardType;
aInfo.iDeviceKeys=KConfigKeyboardDeviceKeys;
aInfo.iAppsKeys=KConfigKeyboardAppsKeys;
}
TInt DKeyboardTemplate::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
{
TInt r=KErrNone;
__KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::HalFunction %d", aFunction));
switch(aFunction)
{
case EKeyboardHalKeyboardInfo:
{
TPckgBuf<TKeyboardInfoV01> kPckg;
KeyboardInfo(kPckg());
Kern::InfoCopy(*(TDes8*)a1,kPckg);
break;
}
case EKeyboardHalSetKeyboardState:
{
if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EKeyboardHalSetKeyboardState")))
return KErrPermissionDenied;
if ((TBool)a1)
{
TThreadMessage& m=Kern::Message();
m.iValue = ETrue;
m.SendReceive(&iMsgQ); // send a message and block Client thread until keyboard has been powered up
}
else
{
TThreadMessage& m=Kern::Message();
m.iValue = EFalse;
m.SendReceive(&iMsgQ); // send a message and block Client thread until keyboard has been powered down
}
}
break;
case EKeyboardHalKeyboardState:
kumemput32(a1, &iKeyboardOn, sizeof(TBool));
break;
default:
r=KErrNotSupported;
break;
}
return r;
}
DECLARE_STANDARD_EXTENSION()
{
__KTRACE_OPT(KEXTENSION,Kern::Printf("Starting keyboard driver"));
// create keyboard driver
TInt r=KErrNoMemory;
DKeyboardTemplate* pK=new DKeyboardTemplate;
if (pK)
r=pK->Create();
__KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));
return r;
}