Update contrib.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // template\template_variant\specific\keyboard.cpp
15 // Access to Template polled keyboard
16 // The code here implements a simple polled keyboard driver.
17 // This is an alternative to the interrupt-driven driver in keyboard_interrupt.cpp.
18 // This example assumes that we have a non-intelligent keyboard
19 // consisting of a number of i/o lines arranged in a grid.
20 // You can use this code as a starting point and modify it to suit
25 #include <template_assp.h>
27 #include <kernel/kpower.h>
32 // The TKeyboardState class is used to encapsulate the state of
33 // the keyboard. i.e which keys are currently being pressed.
34 // To determine which keys are being pressed, typically a voltage
35 // is applied to each row in turn (or column, depending on the hardware)
36 // and the output is read resulting in a bitmask for each row.
38 // For example, the keys could be arranged as follows (where a '1' indicates
39 // that a key is currently being pressed :
43 // Column# 0 1 2 3 4 5 6 7 8 9 A B C D E F KeyCode
45 // 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 to 6F
46 // 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 to 5F
47 // 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 to 4F
48 // 3 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 30 to 3F
49 // Input-> 2 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 20 to 2F
50 // 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 to 1F
51 // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 to 0F
53 // output-> 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0
56 // Modify TKeyboardState (or provide an alternative) to model the
57 // real keyboard state
75 TKeyboardState operator&(const TKeyboardState& aState);
76 TKeyboardState operator|(const TKeyboardState& aState);
77 TKeyboardState operator~();
80 TUint32 iKeyBitMask[KRows];
86 TKeyboardState::TKeyboardState()
92 Clears the array of bitmasks
94 void TKeyboardState::Clear()
96 for (TInt row=0; row<KRows; row++)
101 Determines whether any keys are being pressed by examining the
102 array of bitmasks to determine whether any bits are set
104 @return ETrue if one or more keys are being pressed
106 TBool TKeyboardState::IsKeyReady()
108 for (TInt row=0; row<KRows; row++)
110 if (iKeyBitMask[row] != 0)
118 Scans the array of bitmasks and returns a keycode representing
119 the first bit that it finds that is on.
121 if the first bit on the first row is set, then 1 is returned,
122 if the third bit on the first row is set, then 3 is returned. etc.
124 Once a bit is found it is cleared to avoid reading it again.
126 NB Before calling this function, IsKeyReady() should be called
127 to determine whether a key code is available.
129 @return a 32-bit keycode representing a key that is currently pressed
132 TUint32 TKeyboardState::GetKeyCode()
135 for (TInt row=0; row<KRows; row++)
138 for (TInt col=0; col<KColumns; col++)
140 if (iKeyBitMask[row] & bitMask)
142 iKeyBitMask[row] &= ~bitMask;
153 Perform a bitwise AND between two TKeyboardState objects
154 by AND-ing together all the 32-bit integers
156 @return a new instance of a TKeyboardState object containing the result
158 TKeyboardState TKeyboardState::operator&(const TKeyboardState& aState)
160 TKeyboardState state = *this;
162 for (TInt row=0; row<KRows; row++)
163 state.iKeyBitMask[row]&= aState.iKeyBitMask[row];;
169 Perform a bitwise OR between two TKeyboardState objects
170 by OR-ing together all the 32-bit integers
172 @return a new instance of a TKeyboardState object containing the result
174 TKeyboardState TKeyboardState::operator|(const TKeyboardState& aState)
176 TKeyboardState state = *this;
178 for (TInt row=0; row<KRows; row++)
179 state.iKeyBitMask[row]|= aState.iKeyBitMask[row];;
185 Perform a bitwise NOT (one's complement) of a KeyboardState object
186 by NOT-ing all the 32-bit integers
188 @return a new instance of a TKeyboardState object containing the result
190 TKeyboardState TKeyboardState::operator~()
192 TKeyboardState state = *this;
194 for (TInt row=0; row<KRows; row++)
195 state.iKeyBitMask[row] = ~state.iKeyBitMask[row];
204 // Modify this conversion table to suit your keyboard layout
208 const TUint8 convertCode[] =
211 EStdKeyLeftAlt , EStdKeyHash , EStdKeyNull , EStdKeyLeftCtrl ,
212 EStdKeyLeftFunc , EStdKeyEscape , '1' , '2' ,
213 '9' , '0' , EStdKeyMinus , EStdKeyEquals ,
214 EStdKeyNull , EStdKeyBackspace , EStdKeyNull , EStdKeyNull ,
216 EStdKeyNull , EStdKeyBackSlash , EStdKeyLeftShift , EStdKeyNull ,
217 EStdKeyNull , EStdKeyDelete , EStdKeyNull , 'T' ,
218 'Y' , 'U' , 'I' , EStdKeyEnter ,
219 EStdKeyRightShift , EStdKeyDownArrow , EStdKeyNull , EStdKeyNull ,
221 EStdKeyNull , EStdKeyTab , EStdKeyNull , EStdKeyNull ,
222 EStdKeyNull , 'Q' , 'W' , 'E' ,
223 'R' , 'O' , 'P' , EStdKeySquareBracketLeft ,
224 EStdKeyNull , EStdKeySquareBracketRight,EStdKeyNull , EStdKeyNull ,
226 EStdKeyNull , 'Z' , EStdKeyNull , EStdKeyNull ,
227 EStdKeyNull , EStdKeyCapsLock , EStdKeyNull , EStdKeyNull ,
228 'K' , 'L' , EStdKeySemiColon , EStdKeySingleQuote ,
229 EStdKeyNull , EStdKeyUpArrow , EStdKeyNull , EStdKeyNull ,
231 EStdKeyNull , EStdKeyTab , EStdKeyNull , EStdKeyNull,
232 EStdKeyNull , 'Q' , 'W' , 'E' ,
233 'R' , 'O' , 'P' , EStdKeySquareBracketLeft ,
234 EStdKeyNull , EStdKeySquareBracketRight, EStdKeyNull , EStdKeyNull ,
236 EStdKeyNull , 'X' , EStdKeyNull , EStdKeyNull ,
237 EStdKeyNull , 'C' , 'V' , 'B' ,
238 'N' , 'M' , EStdKeyComma , EStdKeyFullStop ,
239 EStdKeyNull , EStdKeySpace , EStdKeyNull , EStdKeyNull ,
241 EStdKeyNull , EStdKeyNull , EStdKeyNull , EStdKeyNull ,
242 EStdKeyNull , '3' , '4' , '5' ,
243 '6' , '7' , '8' , EStdKeyMenu ,
244 EStdKeyNull , EStdKeyRightArrow , EStdKeyNull , EStdKeyNull
251 const TKeyboard KConfigKeyboardType = EKeyboard_Full;
252 const TInt KConfigKeyboardDeviceKeys = 0;
253 const TInt KConfigKeyboardAppsKeys = 0;
259 // Set the keyboard scan rate in milliseconds
263 const TInt KScanRate = 50; // poll every 1/20 of a second (i.e. every 50 milliseconds)
266 _LIT(KLitKeyboard,"Keyboard");
272 // Add any private functions and data you require
274 NONSHARABLE_CLASS(DKeyboardTemplate) : public DPowerHandler
280 // from DPowerHandler
282 void PowerDown(TPowerState);
285 static void HandleMessage(TAny* aPtr);
286 void HandleMsg(TMessageBase* aMsg);
288 static TInt HalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2);
289 TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
291 static void PowerUpDfcFn(TAny* aPtr);
294 static void PowerDownDfcFn(TAny* aPtr);
297 static void TimerCallback(TAny* aDriver);
298 static void TimerDfcFn(TAny* aDriver);
301 void KeyboardInfo(TKeyboardInfoV01& aInfo);
305 void KeyboardPowerUp();
317 // a bitmask indicating which keys were pressed down on the last timer tick
318 TKeyboardState iKeyStateLast;
320 // a bitmask indicating the set of keys for which we have sent an EKeyDown event
321 TKeyboardState iKeysDown;
327 DKeyboardTemplate::DKeyboardTemplate()
328 : DPowerHandler(KLitKeyboard),
329 iMsgQ(HandleMessage, this, NULL, 1),
330 iPowerUpDfc(PowerUpDfcFn, this, 6),
331 iPowerDownDfc(PowerDownDfcFn, this, 7),
332 iTimer(&DKeyboardTemplate::TimerCallback, (TAny*) this),
333 iTimerDfc(TimerDfcFn, this, 1)
335 // Convert the scan rate from milliseconds to nanokernel ticks (normally 1/64 of a second)
336 iTimerTicks = NKern::TimerTicks(KScanRate);
340 Second-phase constructor
341 Assigns queues for all the DFCs and starts the keyboard-polling timer
343 Called by factory function at ordinal 0
345 TInt DKeyboardTemplate::Create()
347 iDfcQ=Kern::DfcQue0();
349 iKeyboardOn = EFalse;
351 // install the HAL function
352 TInt r = Kern::AddHalEntry(EHalGroupKeyboard, DKeyboardTemplate::HalFunction, this);
356 iTimerDfc.SetDfcQ(iDfcQ);
358 iPowerUpDfc.SetDfcQ(iDfcQ);
359 iPowerDownDfc.SetDfcQ(iDfcQ);
360 iMsgQ.SetDfcQ(iDfcQ);
363 // install the power handler
366 // Power up the device and start the timer
373 Calback for the keyboard-polling timer
374 Called in the context of an ISR
376 @param aPtr A pointer to an instance of DKeyboardTemplate
378 void DKeyboardTemplate::TimerCallback(TAny *aPtr)
381 DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr;
387 DFC scheduled by the keyboard-polling timer when it expires
389 @param aPtr A pointer to an instance of DKeyboardTemplate
391 void DKeyboardTemplate::TimerDfcFn(TAny* aPtr)
393 ((DKeyboardTemplate*)aPtr)->Poll();
398 Reads scan codes from the keyboard until there are none left
399 Called from the keyboard-polling timer's DFC
401 void DKeyboardTemplate::Poll()
403 __KTRACE_OPT(KHARDWARE,Kern::Printf("DKeyboardTemplate::EventDfc"));
406 TKeyboardState keyState;
409 // TO DO: (mandatory)
410 // Read new key state into the array of bitmasks in keyState
411 // This typically involves applying a voltage to each row from 0 to KRows-1,
412 // reading the output state of the i/o lines at every step
413 // - this represents the keys that are pressed on each row -
414 // and storing the output of each row as a bitmask into keyState.iKeyBitMask[n],
415 // where n = the row being accessed
418 // To enable a simple de-bouncing algorithm,
419 // work out which keys have been pressed down for at least two timer
420 // ticks by AND-ing together the last bitmask with the current bitmask
421 TKeyboardState keysStillDown = keyState & iKeyStateLast;
424 // Similarly, work out which keys have been "un-pressed" for at least two timer
425 // ticks by AND-ing together the one's complement of the last bitmask with the
426 // one's complement of the current bitmask and
427 // then AND-ing this with the set of keys for which we have sent an EKeyDown
428 // event to give the set of keys for which we need to send an EKeyUp event
429 TKeyboardState keysStillUp = (~keyState & ~iKeyStateLast) & iKeysDown;
431 // save the current state for next time
432 iKeyStateLast = keyState;
434 // update the set of keys for which we have sent an EKeyDown event
435 iKeysDown = iKeysDown | keysStillDown;
436 iKeysDown = iKeysDown & ~keysStillUp;
438 // process all the key-down events
439 while (keysStillDown.IsKeyReady()) // while there are keys we haven't processed
442 TUint keyCode = keysStillDown.GetKeyCode(); // Read keycodes from bitmask
444 __KTRACE_OPT(KHARDWARE,Kern::Printf("EKeyDown: #%02x\n",keyCode));
447 // TO DO: (mandatory)
449 // Convert from hardware scancode to EPOC scancode and send the scancode as an event (key pressed or released)
450 // as per below EXAMPLE ONLY:
452 __ASSERT_DEBUG(keyCode < (sizeof(convertCode) / sizeof(TUint8)), Kern::Fault("Keyboard", __LINE__));
453 TUint8 stdKey = convertCode[keyCode];
455 e.Set(TRawEvent::EKeyDown, stdKey, 0);
459 // process all the key-up events
460 while (keysStillUp.IsKeyReady()) // while there are keys we haven't processed
463 TUint keyCode = keysStillUp.GetKeyCode(); // Read keycodes from bitmask
465 __KTRACE_OPT(KHARDWARE,Kern::Printf("EKeyUp: #%02x\n",keyCode));
468 // TO DO: (mandatory)
470 // Convert from hardware scancode to EPOC scancode and send the scancode as an event (key pressed or released)
471 // as per below EXAMPLE ONLY:
473 __ASSERT_DEBUG(keyCode < (sizeof(convertCode) / sizeof(TUint8)), Kern::Fault("Keyboard", __LINE__));
474 TUint8 stdKey = convertCode[keyCode];
476 e.Set(TRawEvent::EKeyUp, stdKey, 0);
480 // start the timer again
481 iTimer.OneShot(iTimerTicks);
487 Notifies the peripheral of system power up.
488 Called by the power manager during a transition from standby.
489 Schedules a DFC to handle the power up.
491 void DKeyboardTemplate::PowerUp()
498 static DFC to handle powering up the keyboard
500 @param aPtr A pointer to an instance of DKeyboardTemplate
502 void DKeyboardTemplate::PowerUpDfcFn(TAny* aPtr)
504 ((DKeyboardTemplate*)aPtr)->PowerUpDfc();
509 DFC to handle powering up the keyboard
511 void DKeyboardTemplate::PowerUpDfc()
513 __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerUpDfc()"));
516 // Indicate to power handle that powered up is complete
521 Powers up the keyboard
522 May be called as a result of a power transition or from the HAL
524 void DKeyboardTemplate::KeyboardOn()
526 __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOn() iKeyboardOn=%d", iKeyboardOn));
528 if (!iKeyboardOn) // make sure we don't initialize more than once
533 Powers up the keyboard
534 Assumes that the keyboard is currently powered off
536 void DKeyboardTemplate::KeyboardPowerUp()
538 __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardPowerUp()"));
542 iKeyStateLast.Clear();
545 // Send key up events for EStdKeyOff (Fn+Esc) event
547 e.Set(TRawEvent::EKeyUp,EStdKeyEscape,0);
549 e.Set(TRawEvent::EKeyUp,EStdKeyLeftFunc,0);
552 // Start the periodic tick for the selected rate.
553 // This will call TimerCallback() in the context of an ISR
554 iTimer.OneShot(iTimerTicks);
559 Requests keyboard to power down.
560 Called by the power manager during a transition to standby or power off
561 Schedules a DFC to handle the power up.
563 @param aPowerState the current power state
565 void DKeyboardTemplate::PowerDown(TPowerState)
567 iPowerDownDfc.Enque();
571 static DFC to handle powering down the keyboard
573 @param aPtr A pointer to an instance of DKeyboardTemplate
575 void DKeyboardTemplate::PowerDownDfcFn(TAny* aPtr)
577 ((DKeyboardTemplate*)aPtr)->PowerDownDfc();
581 DFC to handle powering down the keyboard
583 void DKeyboardTemplate::PowerDownDfc()
585 __KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerDownDfc()"));
591 Powers down the keyboard
592 May be called as a result of a power transition or from the HAL
594 void DKeyboardTemplate::KeyboardOff()
596 __KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOff() iKeyboardOn=%d", iKeyboardOn));
598 // cancel the keyboard-polling timer
602 iKeyboardOn = EFalse;
607 static message handler for processing power up/down messages
608 posted internally from HalFunction()
610 @param aPtr A pointer to an instance of DKeyboardTemplate
612 void DKeyboardTemplate::HandleMessage(TAny* aPtr)
614 DKeyboardTemplate& h=*(DKeyboardTemplate*)aPtr;
615 TMessageBase* pM=h.iMsgQ.iMessage;
621 Message handler for processing power up/down messages
622 posted internally from HalFunction()
624 param aMsg A message indicating whether to power the keyboard on or off
626 void DKeyboardTemplate::HandleMsg(TMessageBase* aMsg)
632 aMsg->Complete(KErrNone,ETrue);
637 Retrieves information about the keyboard
638 Called from HalFunction()
640 @param aInfo a caller-supplied class which on return contains information about the keyboard
642 void DKeyboardTemplate::KeyboardInfo(TKeyboardInfoV01& aInfo)
644 __KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::KeyboardInfo"));
645 aInfo.iKeyboardType=KConfigKeyboardType;
646 aInfo.iDeviceKeys=KConfigKeyboardDeviceKeys;
647 aInfo.iAppsKeys=KConfigKeyboardAppsKeys;
654 @param aPtr a pointer to an instance of DLcdPowerHandler
655 @param aFunction the function number
656 @param a1 an arbitrary parameter
657 @param a2 an arbitrary parameter
659 TInt DKeyboardTemplate::HalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
661 DKeyboardTemplate* pH=(DKeyboardTemplate*)aPtr;
662 return pH->HalFunction(aFunction,a1,a2);
667 a HAL entry handling function for HAL group attribute EHalGroupKeyboard
669 @param a1 an arbitrary argument
670 @param a2 an arbitrary argument
671 @return KErrNone if successful
673 TInt DKeyboardTemplate::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
677 __KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::HalFunction %d", aFunction));
681 case EKeyboardHalKeyboardInfo:
683 TPckgBuf<TKeyboardInfoV01> kPckg;
684 KeyboardInfo(kPckg());
685 Kern::InfoCopy(*(TDes8*)a1,kPckg);
689 case EKeyboardHalSetKeyboardState:
691 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EKeyboardHalSetKeyboardState")))
692 return KErrPermissionDenied;
695 TThreadMessage& m=Kern::Message();
697 m.SendReceive(&iMsgQ); // send a message and block Client thread until keyboard has been powered up
701 TThreadMessage& m=Kern::Message();
703 m.SendReceive(&iMsgQ); // send a message and block Client thread until keyboard has been powered down
708 case EKeyboardHalKeyboardState:
709 kumemput32(a1, &iKeyboardOn, sizeof(TBool));
721 DECLARE_STANDARD_EXTENSION()
723 __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting keyboard driver"));
725 // create keyboard driver
727 DKeyboardTemplate* pK=new DKeyboardTemplate;
731 __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));