--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bsptemplate/asspandvariant/template_variant/specific/keyboard.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,733 @@
+// 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 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 polled keyboard
+// The code here implements a simple polled keyboard driver.
+// This is an alternative to the interrupt-driven driver in keyboard_interrupt.cpp.
+// This example assumes that we have a non-intelligent keyboard
+// consisting of a number of i/o lines arranged in a grid.
+// You can use this code as a starting point and modify it to suit
+// your hardware.
+//
+//
+
+#include <template_assp.h>
+#include "platform.h"
+#include <kernel/kpower.h>
+#include <e32keys.h>
+
+
+
+// The TKeyboardState class is used to encapsulate the state of
+// the keyboard. i.e which keys are currently being pressed.
+// To determine which keys are being pressed, typically a voltage
+// is applied to each row in turn (or column, depending on the hardware)
+// and the output is read resulting in a bitmask for each row.
+//
+// For example, the keys could be arranged as follows (where a '1' indicates
+// that a key is currently being pressed :
+// EXAMPLE ONLY
+//
+// Translated
+// Column# 0 1 2 3 4 5 6 7 8 9 A B C D E F KeyCode
+// Row#
+// 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 to 6F
+// 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 to 5F
+// 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 to 4F
+// 3 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 30 to 3F
+// Input-> 2 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 20 to 2F
+// 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 to 1F
+// 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 to 0F
+//
+// output-> 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0
+//
+// TO DO: (mandadory)
+// Modify TKeyboardState (or provide an alternative) to model the
+// real keyboard state
+//
+// EXAMPLE ONLY
+class TKeyboardState
+ {
+public:
+
+ enum TDimensions
+ {
+ KRows = 7,
+ KColumns = 16
+ };
+
+public:
+ TKeyboardState();
+ void Clear();
+ TBool IsKeyReady();
+ TUint32 GetKeyCode();
+ TKeyboardState operator&(const TKeyboardState& aState);
+ TKeyboardState operator|(const TKeyboardState& aState);
+ TKeyboardState operator~();
+
+public:
+ TUint32 iKeyBitMask[KRows];
+ };
+
+/**
+Constructor
+*/
+TKeyboardState::TKeyboardState()
+ {
+ Clear();
+ }
+
+/**
+Clears the array of bitmasks
+*/
+void TKeyboardState::Clear()
+ {
+ for (TInt row=0; row<KRows; row++)
+ iKeyBitMask[row] = 0;
+ }
+
+/**
+Determines whether any keys are being pressed by examining the
+array of bitmasks to determine whether any bits are set
+
+@return ETrue if one or more keys are being pressed
+*/
+TBool TKeyboardState::IsKeyReady()
+ {
+ for (TInt row=0; row<KRows; row++)
+ {
+ if (iKeyBitMask[row] != 0)
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+/**
+Scans the array of bitmasks and returns a keycode representing
+the first bit that it finds that is on.
+E.g. :
+if the first bit on the first row is set, then 1 is returned,
+if the third bit on the first row is set, then 3 is returned. etc.
+
+Once a bit is found it is cleared to avoid reading it again.
+
+NB Before calling this function, IsKeyReady() should be called
+to determine whether a key code is available.
+
+@return a 32-bit keycode representing a key that is currently pressed
+*/
+
+TUint32 TKeyboardState::GetKeyCode()
+ {
+ TInt keyNum = 0;
+ for (TInt row=0; row<KRows; row++)
+ {
+ TUint32 bitMask = 1;
+ for (TInt col=0; col<KColumns; col++)
+ {
+ if (iKeyBitMask[row] & bitMask)
+ {
+ iKeyBitMask[row] &= ~bitMask;
+ return keyNum;
+ }
+ bitMask<<= 1;
+ keyNum++;
+ }
+ }
+ return 0;
+ }
+
+/**
+Perform a bitwise AND between two TKeyboardState objects
+by AND-ing together all the 32-bit integers
+
+@return a new instance of a TKeyboardState object containing the result
+*/
+TKeyboardState TKeyboardState::operator&(const TKeyboardState& aState)
+ {
+ TKeyboardState state = *this;
+
+ for (TInt row=0; row<KRows; row++)
+ state.iKeyBitMask[row]&= aState.iKeyBitMask[row];;
+
+ return state;
+ }
+
+/**
+Perform a bitwise OR between two TKeyboardState objects
+by OR-ing together all the 32-bit integers
+
+@return a new instance of a TKeyboardState object containing the result
+*/
+TKeyboardState TKeyboardState::operator|(const TKeyboardState& aState)
+ {
+ TKeyboardState state = *this;
+
+ for (TInt row=0; row<KRows; row++)
+ state.iKeyBitMask[row]|= aState.iKeyBitMask[row];;
+
+ return state;
+ }
+
+/**
+Perform a bitwise NOT (one's complement) of a KeyboardState object
+by NOT-ing all the 32-bit integers
+
+@return a new instance of a TKeyboardState object containing the result
+*/
+TKeyboardState TKeyboardState::operator~()
+ {
+ TKeyboardState state = *this;
+
+ for (TInt row=0; row<KRows; row++)
+ state.iKeyBitMask[row] = ~state.iKeyBitMask[row];
+
+ return state;
+ }
+
+//
+//
+// TO DO: (optional)
+//
+// Modify this conversion table to suit your keyboard layout
+// EXAMPLE ONLY
+//
+
+const TUint8 convertCode[] =
+ {
+//Row 0 (bottom row)
+ EStdKeyLeftAlt , EStdKeyHash , EStdKeyNull , EStdKeyLeftCtrl ,
+ EStdKeyLeftFunc , EStdKeyEscape , '1' , '2' ,
+ '9' , '0' , EStdKeyMinus , EStdKeyEquals ,
+ EStdKeyNull , EStdKeyBackspace , EStdKeyNull , EStdKeyNull ,
+//Row 1
+ EStdKeyNull , EStdKeyBackSlash , EStdKeyLeftShift , EStdKeyNull ,
+ EStdKeyNull , EStdKeyDelete , EStdKeyNull , 'T' ,
+ 'Y' , 'U' , 'I' , EStdKeyEnter ,
+ EStdKeyRightShift , EStdKeyDownArrow , EStdKeyNull , EStdKeyNull ,
+//Row 2
+ EStdKeyNull , EStdKeyTab , EStdKeyNull , EStdKeyNull ,
+ EStdKeyNull , 'Q' , 'W' , 'E' ,
+ 'R' , 'O' , 'P' , EStdKeySquareBracketLeft ,
+ EStdKeyNull , EStdKeySquareBracketRight,EStdKeyNull , EStdKeyNull ,
+//Row 3
+ EStdKeyNull , 'Z' , EStdKeyNull , EStdKeyNull ,
+ EStdKeyNull , EStdKeyCapsLock , EStdKeyNull , EStdKeyNull ,
+ 'K' , 'L' , EStdKeySemiColon , EStdKeySingleQuote ,
+ EStdKeyNull , EStdKeyUpArrow , EStdKeyNull , EStdKeyNull ,
+//Row 4
+ EStdKeyNull , EStdKeyTab , EStdKeyNull , EStdKeyNull,
+ EStdKeyNull , 'Q' , 'W' , 'E' ,
+ 'R' , 'O' , 'P' , EStdKeySquareBracketLeft ,
+ EStdKeyNull , EStdKeySquareBracketRight, EStdKeyNull , EStdKeyNull ,
+//Row 5
+ EStdKeyNull , 'X' , EStdKeyNull , EStdKeyNull ,
+ EStdKeyNull , 'C' , 'V' , 'B' ,
+ 'N' , 'M' , EStdKeyComma , EStdKeyFullStop ,
+ EStdKeyNull , EStdKeySpace , EStdKeyNull , EStdKeyNull ,
+//Row 6
+ EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,
+ EStdKeyNull , '3' , '4' , '5' ,
+ '6' , '7' , '8' , EStdKeyMenu ,
+ EStdKeyNull , EStdKeyRightArrow , EStdKeyNull , EStdKeyNull
+ };
+
+
+
+
+// EXAMPLE ONLY
+const TKeyboard KConfigKeyboardType = EKeyboard_Full;
+const TInt KConfigKeyboardDeviceKeys = 0;
+const TInt KConfigKeyboardAppsKeys = 0;
+
+
+//
+// TO DO: (optional)
+//
+// Set the keyboard scan rate in milliseconds
+//
+
+// EXAMPLE ONLY
+const TInt KScanRate = 50; // poll every 1/20 of a second (i.e. every 50 milliseconds)
+
+
+_LIT(KLitKeyboard,"Keyboard");
+
+
+//
+// TO DO: (optional)
+//
+// Add any private functions and data you require
+//
+NONSHARABLE_CLASS(DKeyboardTemplate) : public DPowerHandler
+ {
+public:
+ DKeyboardTemplate();
+ TInt Create();
+
+ // from DPowerHandler
+ void PowerUp();
+ void PowerDown(TPowerState);
+
+private:
+ static void HandleMessage(TAny* aPtr);
+ void HandleMsg(TMessageBase* aMsg);
+
+ static TInt HalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2);
+ TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
+
+ static void PowerUpDfcFn(TAny* aPtr);
+ void PowerUpDfc();
+
+ static void PowerDownDfcFn(TAny* aPtr);
+ void PowerDownDfc();
+
+ static void TimerCallback(TAny* aDriver);
+ static void TimerDfcFn(TAny* aDriver);
+ void Poll();
+
+ void KeyboardInfo(TKeyboardInfoV01& aInfo);
+
+ void KeyboardOn();
+ void KeyboardOff();
+ void KeyboardPowerUp();
+
+private:
+ TDfcQue* iDfcQ;
+ TMessageQue iMsgQ;
+ TDfc iPowerUpDfc;
+ TDfc iPowerDownDfc;
+ TBool iKeyboardOn;
+ NTimer iTimer;
+ TInt iTimerTicks;
+ TDfc iTimerDfc;
+
+ // a bitmask indicating which keys were pressed down on the last timer tick
+ TKeyboardState iKeyStateLast;
+
+ // a bitmask indicating the set of keys for which we have sent an EKeyDown event
+ TKeyboardState iKeysDown;
+ };
+
+/**
+constructor
+*/
+DKeyboardTemplate::DKeyboardTemplate()
+ : DPowerHandler(KLitKeyboard),
+ iMsgQ(HandleMessage, this, NULL, 1),
+ iPowerUpDfc(PowerUpDfcFn, this, 6),
+ iPowerDownDfc(PowerDownDfcFn, this, 7),
+ iTimer(&DKeyboardTemplate::TimerCallback, (TAny*) this),
+ iTimerDfc(TimerDfcFn, this, 1)
+ {
+ // Convert the scan rate from milliseconds to nanokernel ticks (normally 1/64 of a second)
+ iTimerTicks = NKern::TimerTicks(KScanRate);
+ }
+
+/**
+Second-phase constructor
+Assigns queues for all the DFCs and starts the keyboard-polling timer
+
+Called by factory function at ordinal 0
+*/
+TInt DKeyboardTemplate::Create()
+ {
+ iDfcQ=Kern::DfcQue0();
+
+ iKeyboardOn = EFalse;
+
+ // install the HAL function
+ TInt r = Kern::AddHalEntry(EHalGroupKeyboard, DKeyboardTemplate::HalFunction, this);
+ if (r != KErrNone)
+ return r;
+
+ iTimerDfc.SetDfcQ(iDfcQ);
+
+ iPowerUpDfc.SetDfcQ(iDfcQ);
+ iPowerDownDfc.SetDfcQ(iDfcQ);
+ iMsgQ.SetDfcQ(iDfcQ);
+ iMsgQ.Receive();
+
+ // install the power handler
+ Add();
+
+ // Power up the device and start the timer
+ KeyboardPowerUp();
+
+ return r;
+ }
+
+/**
+Calback for the keyboard-polling timer
+Called in the context of an ISR
+
+@param aPtr A pointer to an instance of DKeyboardTemplate
+*/
+void DKeyboardTemplate::TimerCallback(TAny *aPtr)
+ {
+ // schedule a DFC
+ DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr;
+ k.iTimerDfc.Add();
+ }
+
+
+/**
+DFC scheduled by the keyboard-polling timer when it expires
+
+@param aPtr A pointer to an instance of DKeyboardTemplate
+*/
+void DKeyboardTemplate::TimerDfcFn(TAny* aPtr)
+ {
+ ((DKeyboardTemplate*)aPtr)->Poll();
+ }
+
+
+/**
+Reads scan codes from the keyboard until there are none left
+Called from the keyboard-polling timer's DFC
+*/
+void DKeyboardTemplate::Poll()
+ {
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("DKeyboardTemplate::EventDfc"));
+
+
+ TKeyboardState keyState;
+
+ //
+ // TO DO: (mandatory)
+ // Read new key state into the array of bitmasks in keyState
+ // This typically involves applying a voltage to each row from 0 to KRows-1,
+ // reading the output state of the i/o lines at every step
+ // - this represents the keys that are pressed on each row -
+ // and storing the output of each row as a bitmask into keyState.iKeyBitMask[n],
+ // where n = the row being accessed
+ //
+
+ // To enable a simple de-bouncing algorithm,
+ // work out which keys have been pressed down for at least two timer
+ // ticks by AND-ing together the last bitmask with the current bitmask
+ TKeyboardState keysStillDown = keyState & iKeyStateLast;
+
+
+ // Similarly, work out which keys have been "un-pressed" for at least two timer
+ // ticks by AND-ing together the one's complement of the last bitmask with the
+ // one's complement of the current bitmask and
+ // then AND-ing this with the set of keys for which we have sent an EKeyDown
+ // event to give the set of keys for which we need to send an EKeyUp event
+ TKeyboardState keysStillUp = (~keyState & ~iKeyStateLast) & iKeysDown;
+
+ // save the current state for next time
+ iKeyStateLast = keyState;
+
+ // update the set of keys for which we have sent an EKeyDown event
+ iKeysDown = iKeysDown | keysStillDown;
+ iKeysDown = iKeysDown & ~keysStillUp;
+
+ // process all the key-down events
+ while (keysStillDown.IsKeyReady()) // while there are keys we haven't processed
+ {
+ TRawEvent e;
+ TUint keyCode = keysStillDown.GetKeyCode(); // Read keycodes from bitmask
+
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("EKeyDown: #%02x\n",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:
+ //
+ __ASSERT_DEBUG(keyCode < (sizeof(convertCode) / sizeof(TUint8)), Kern::Fault("Keyboard", __LINE__));
+ TUint8 stdKey = convertCode[keyCode];
+
+ e.Set(TRawEvent::EKeyDown, stdKey, 0);
+ Kern::AddEvent(e);
+ }
+
+ // process all the key-up events
+ while (keysStillUp.IsKeyReady()) // while there are keys we haven't processed
+ {
+ TRawEvent e;
+ TUint keyCode = keysStillUp.GetKeyCode(); // Read keycodes from bitmask
+
+ __KTRACE_OPT(KHARDWARE,Kern::Printf("EKeyUp: #%02x\n",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:
+ //
+ __ASSERT_DEBUG(keyCode < (sizeof(convertCode) / sizeof(TUint8)), Kern::Fault("Keyboard", __LINE__));
+ TUint8 stdKey = convertCode[keyCode];
+
+ e.Set(TRawEvent::EKeyUp, stdKey, 0);
+ Kern::AddEvent(e);
+ }
+
+ // start the timer again
+ iTimer.OneShot(iTimerTicks);
+ }
+
+
+
+/**
+Notifies the peripheral of system power up.
+Called by the power manager during a transition from standby.
+Schedules a DFC to handle the power up.
+*/
+void DKeyboardTemplate::PowerUp()
+ {
+ iPowerUpDfc.Enque();
+ }
+
+
+/**
+static DFC to handle powering up the keyboard
+
+@param aPtr A pointer to an instance of DKeyboardTemplate
+*/
+void DKeyboardTemplate::PowerUpDfcFn(TAny* aPtr)
+ {
+ ((DKeyboardTemplate*)aPtr)->PowerUpDfc();
+ }
+
+
+/**
+DFC to handle powering up the keyboard
+*/
+void DKeyboardTemplate::PowerUpDfc()
+ {
+ __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerUpDfc()"));
+ KeyboardOn();
+
+ // Indicate to power handle that powered up is complete
+ PowerUpDone();
+ }
+
+/**
+Powers up the keyboard
+May be called as a result of a power transition or from the HAL
+*/
+void DKeyboardTemplate::KeyboardOn()
+ {
+ __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOn() iKeyboardOn=%d", iKeyboardOn));
+
+ if (!iKeyboardOn) // make sure we don't initialize more than once
+ KeyboardPowerUp();
+ }
+
+/**
+Powers up the keyboard
+Assumes that the keyboard is currently powered off
+*/
+void DKeyboardTemplate::KeyboardPowerUp()
+ {
+ __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardPowerUp()"));
+
+ iKeyboardOn = ETrue;
+
+ iKeyStateLast.Clear();
+ iKeysDown.Clear();
+
+ // 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);
+
+ // Start the periodic tick for the selected rate.
+ // This will call TimerCallback() in the context of an ISR
+ iTimer.OneShot(iTimerTicks);
+ }
+
+
+/**
+Requests keyboard to power down.
+Called by the power manager during a transition to standby or power off
+Schedules a DFC to handle the power up.
+
+@param aPowerState the current power state
+*/
+void DKeyboardTemplate::PowerDown(TPowerState)
+ {
+ iPowerDownDfc.Enque();
+ }
+
+/**
+static DFC to handle powering down the keyboard
+
+@param aPtr A pointer to an instance of DKeyboardTemplate
+*/
+void DKeyboardTemplate::PowerDownDfcFn(TAny* aPtr)
+ {
+ ((DKeyboardTemplate*)aPtr)->PowerDownDfc();
+ }
+
+/**
+DFC to handle powering down the keyboard
+*/
+void DKeyboardTemplate::PowerDownDfc()
+ {
+ __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerDownDfc()"));
+ KeyboardOff();
+ PowerDownDone();
+ }
+
+/**
+Powers down the keyboard
+May be called as a result of a power transition or from the HAL
+*/
+void DKeyboardTemplate::KeyboardOff()
+ {
+ __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOff() iKeyboardOn=%d", iKeyboardOn));
+
+ // cancel the keyboard-polling timer
+ iTimerDfc.Cancel();
+ iTimer.Cancel();
+
+ iKeyboardOn = EFalse;
+ }
+
+
+/**
+static message handler for processing power up/down messages
+posted internally from HalFunction()
+
+@param aPtr A pointer to an instance of DKeyboardTemplate
+*/
+void DKeyboardTemplate::HandleMessage(TAny* aPtr)
+ {
+ DKeyboardTemplate& h=*(DKeyboardTemplate*)aPtr;
+ TMessageBase* pM=h.iMsgQ.iMessage;
+ if (pM)
+ h.HandleMsg(pM);
+ }
+
+/**
+Message handler for processing power up/down messages
+posted internally from HalFunction()
+
+param aMsg A message indicating whether to power the keyboard on or off
+*/
+void DKeyboardTemplate::HandleMsg(TMessageBase* aMsg)
+ {
+ if (aMsg->iValue)
+ KeyboardOn();
+ else
+ KeyboardOff();
+ aMsg->Complete(KErrNone,ETrue);
+ }
+
+
+/**
+Retrieves information about the keyboard
+Called from HalFunction()
+
+@param aInfo a caller-supplied class which on return contains information about the keyboard
+*/
+void DKeyboardTemplate::KeyboardInfo(TKeyboardInfoV01& aInfo)
+ {
+ __KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::KeyboardInfo"));
+ aInfo.iKeyboardType=KConfigKeyboardType;
+ aInfo.iDeviceKeys=KConfigKeyboardDeviceKeys;
+ aInfo.iAppsKeys=KConfigKeyboardAppsKeys;
+ }
+
+
+/**
+HAL handler function
+
+@param aPtr a pointer to an instance of DLcdPowerHandler
+@param aFunction the function number
+@param a1 an arbitrary parameter
+@param a2 an arbitrary parameter
+*/
+TInt DKeyboardTemplate::HalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
+ {
+ DKeyboardTemplate* pH=(DKeyboardTemplate*)aPtr;
+ return pH->HalFunction(aFunction,a1,a2);
+ }
+
+
+/**
+a HAL entry handling function for HAL group attribute EHalGroupKeyboard
+
+@param a1 an arbitrary argument
+@param a2 an arbitrary argument
+@return KErrNone if successful
+*/
+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;
+ }