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