diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/PDK/Source/GUID-2E42E7EA-FED8-522C-8A5F-F65D799476C9.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/PDK/Source/GUID-2E42E7EA-FED8-522C-8A5F-F65D799476C9.dita Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,124 @@ + + + + + +Keyboard +Driver Implementation Tutorial +

This topic describes how to implement an interrupt driven keyboard driver.

+

The steps are:

+
    +
  • Implement the driver +entry point function and initialisation code. This function is called when +the extension is loaded.

    The initialisation code binds the hardware +interrupt to the Interrupt Service Routine (ISR) and enables the interrupt.

  • +
  • Implement an ISR to +handle key events. The ISR queues a keyboard DFC.

  • +
  • Implement a keyboard +DFC. This function interrogates the keyboard, converts the scancode to a keypress +event, and places it onto the kernel's event queue.

  • +
+
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. +On the template reference board, this is implemented as:

void DKeyboardTemplate::Isr(TAny* aPtr) + { + DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr; + Interrupt::Disable(KIntIdKeyboard); + 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