diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-2E42E7EA-FED8-522C-8A5F-F65D799476C9.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-2E42E7EA-FED8-522C-8A5F-F65D799476C9.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,131 @@ + + + + + +Keyboard Driver Implementation TutorialThis topic describes how to implement an interrupt driven +keyboard driver. +

The steps are:

+ +
Set +Up

In the template reference board port, the .mmp file for the keyboard driver is ...\template_variant\exkey_inttemplate.mmp. This is one of the PRJ_MMPFILES referenced in the template variant's bld.inf file in the ...\template_variant\... directory, and means that the keyboard driver is built as part of +the Variant.

The source for the driver is contained entirely +within ...\template_variant\specific\keyboard_interrupt.cpp.

The driver is defined as a kernel extension and is loaded +early in the boot sequence.

+
Entry +point implementation

The driver functionality is encapsulated +by the DKeyboardTemplate class, and an instance of +this is created when the extension is loaded.

As the driver +is a kernel extension, it must have a DECLARE_STANDARD_EXTENSION() statement. In the template port, this is implemented:

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; + } + +

It simply creates an instance of the DKeyboardTemplate class and then performs a second-phase initialisation, which is +a common pattern in Symbian platform and third party applications.

Initialisation on construction

The constructor +of the DKeyboardTemplate class has the following +signature:

DKeyboardTemplate::DKeyboardTemplate() + : DPowerHandler(KLitKeyboard), + iMsgQ(rxMsg,this,NULL,1), + iPowerUpDfc(PowerUpDfcFn,this,6), + iPowerDownDfc(PowerDownDfcFn,this,7), + iEventDfc(EventDfcFn,this,1) + { + } + +

See also Interrupt Dispatcher +Tutorial.

+
Interrupt +Service Routine (ISR) implementation

The ISR (Interrupt +Service Routine) just schedules the DFC that handles the keypress. +It can also optionally contribute the timing of key interrupts as +a source of random data for the Random Number Generator (see CSPRNG Implementation +in Kernel). On the template reference board, this is implemented +as:

void DKeyboardTemplate::Isr(TAny* aPtr) + { + Interrupt::Disable(KIntIdKeyboard); + + // Add the timing of key interrupts as entropy data for the RNG + Interrupt::AddTimingEntropy(); + + k.iEventDfc.Add(); + } +

The ISR disables the keyboard interrupt, as repeated +ISRs are not allowed to queue further DFC routines.

+
DFC +function implementation

The DFC is the function DKeyboardTemplate::EventDfcFn which is implemented as a +call to DKeyboardTemplate::EventDfc().

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); + }

This:

    +
  • reads the scan +code data by calling DKeyboardTemplate::GetKeyCode()

  • +
  • re-enables the +keyboard interrupt, now that the DFC has freed up the input data register

  • +
  • translates the +keypress event into a Symbian scancode

  • +
  • puts the translated +event on to the event queue.

  • +
+
See +also

Concepts

+
\ No newline at end of file