diff -r 000000000000 -r 5de814552237 navienginebsp/ne1_tb/specific/keyboard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/navienginebsp/ne1_tb/specific/keyboard.cpp Tue Sep 28 18:00:05 2010 +0100 @@ -0,0 +1,736 @@ +/* +* 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: +* ne1_tb\specific\keyboard.cpp +* Access to NE1_TBVariant 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 +#include "platform.h" +#include +#include + + + +// 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; rowPoll(); + } + + +/** +Reads scan codes from the keyboard until there are none left +Called from the keyboard-polling timer's DFC +*/ +void DKeyboardNE1_TB::Poll() + { + __KTRACE_OPT(KHARDWARE,Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB::PowerUp() + { + iPowerUpDfc.Enque(); + } + + +/** +static DFC to handle powering up the keyboard + +@param aPtr A pointer to an instance of DKeyboardNE1_TB +*/ +void DKeyboardNE1_TB::PowerUpDfcFn(TAny* aPtr) + { + ((DKeyboardNE1_TB*)aPtr)->PowerUpDfc(); + } + + +/** +DFC to handle powering up the keyboard +*/ +void DKeyboardNE1_TB::PowerUpDfc() + { + __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB::KeyboardOn() + { + __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB::KeyboardPowerUp() + { + __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB::PowerDown(TPowerState) + { + iPowerDownDfc.Enque(); + } + +/** +static DFC to handle powering down the keyboard + +@param aPtr A pointer to an instance of DKeyboardNE1_TB +*/ +void DKeyboardNE1_TB::PowerDownDfcFn(TAny* aPtr) + { + ((DKeyboardNE1_TB*)aPtr)->PowerDownDfc(); + } + +/** +DFC to handle powering down the keyboard +*/ +void DKeyboardNE1_TB::PowerDownDfc() + { + __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardNE1_TB::PowerDownDfc()")); + KeyboardOff(); + PowerDownDone(); + } + +/** +Powers down the keyboard +May be called as a result of a power transition or from the HAL +*/ +void DKeyboardNE1_TB::KeyboardOff() + { + __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB +*/ +void DKeyboardNE1_TB::HandleMessage(TAny* aPtr) + { + DKeyboardNE1_TB& h=*(DKeyboardNE1_TB*)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 DKeyboardNE1_TB::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 DKeyboardNE1_TB::KeyboardInfo(TKeyboardInfoV01& aInfo) + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardNE1_TB::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 DKeyboardNE1_TB::HalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) + { + DKeyboardNE1_TB* pH=(DKeyboardNE1_TB*)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 DKeyboardNE1_TB::HalFunction(TInt aFunction, TAny* a1, TAny* a2) + { + TInt r=KErrNone; + + __KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardNE1_TB::HalFunction %d", aFunction)); + + switch(aFunction) + { + case EKeyboardHalKeyboardInfo: + { + TPckgBuf 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; + DKeyboardNE1_TB* pK=new DKeyboardNE1_TB; + if (pK) + r=pK->Create(); + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + }