os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/specific/keyboard_interrupt.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // template\template_variant\specific\keyboard.cpp
    15 // Access to Template interruptible keyboard
    16 // The code here implements a simple interrupt-driven keyboard driver.
    17 // This is an alternative to the polled driver in keyboard.cpp.
    18 // This example assumes that we have an intelligent keyboard controller
    19 // which:
    20 // scans the keyboard automatically
    21 // generates an interrupt when a key is pressed or released
    22 // You can use this code as a starting point and modify it to suit
    23 // your hardware.
    24 // 
    25 //
    26 
    27 #include <template_assp.h>
    28 #include "iolines.h"
    29 #include "platform.h"
    30 #include <kernel/kpower.h>
    31 #include <e32keys.h>
    32 //
    33 //
    34 // TO DO: (optional)
    35 //
    36 // Modify this conversion table to suit your keyboard layout
    37 //
    38 // This example assumes that the following keyboard layout:
    39 //
    40 // <----Row0-----><-----Row1-------><---Row2-----><-----Row3-------><-------Row4-----------><------Row5------><-----Row6-------><---Row7--->
    41 //		LAlt																																Column0
    42 //		'				\				TAB				Z					A						X										Column1
    43 //						LShift																												Column2
    44 //		LCtrl																																Column3
    45 //		Fn																																	Column4
    46 //		Esc				Del				Q				CapLk				S						C				3						Column5
    47 //		1								W									D						V				4						Column6
    48 //		2				T				E									F						B				5						Column7
    49 //		9				Y				R				K					G						N				6						Column8
    50 //		0				U				O				L					H						M				7						Column9
    51 //		-				I				P				;					J						,				8						Column10
    52 //		=				Enter			[				'					/						.				Prog					Column11
    53 //						RShift																												Column12
    54 //		BkSp			DnArrow			]				UpArrow				LeftArrow				Space			RightArrow				Column13
    55 //																																			Column14
    56 //																																			Column15
    57 // EXAMPLE ONLY
    58 const TUint8 convertCode[] =
    59 	{
    60 	EStdKeyNull ,   EStdKeyLeftAlt  ,  EStdKeyNull   ,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column0
    61 	EStdKeyNull ,   EStdKeyHash     ,EStdKeyBackSlash,   EStdKeyTab     ,          'Z'          ,       'A'         ,       'X'         ,EStdKeyNull,       // Column1
    62 	EStdKeyNull ,    EStdKeyNull    ,EStdKeyLeftShift,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column2
    63 	EStdKeyNull ,  EStdKeyLeftCtrl  ,  EStdKeyNull   ,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column3
    64 	EStdKeyNull ,  EStdKeyLeftFunc  ,  EStdKeyNull   ,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column4
    65 	EStdKeyNull ,   EStdKeyEscape   , EStdKeyDelete  ,      'Q'         ,      EStdKeyCapsLock  ,       'S'         ,        'C'        ,   '3'     ,       // Column5
    66 	EStdKeyNull ,       '1'         ,  EStdKeyNull   ,      'W'         ,      EStdKeyNull      ,       'D'         ,        'V'        ,   '4'     ,       // Column6
    67 	EStdKeyNull ,       '2'         ,     'T'        ,      'E'         ,      EStdKeyNull      ,       'F'         ,        'B'        ,   '5'     ,       // Column7
    68 	EStdKeyNull ,       '9'         ,     'Y'        ,      'R'         ,          'K'          ,       'G'         ,        'N'        ,   '6'     ,       // Column8
    69 	EStdKeyNull ,       '0'         ,     'U'        ,      'O'         ,          'L'          ,       'H'         ,        'M'        ,   '7'     ,       // Column9
    70 	EStdKeyNull ,    EStdKeyMinus   ,     'I'        ,      'P'         ,    EStdKeySemiColon   ,       'J'         ,    EStdKeyComma   ,   '8'     ,       // Column10
    71 	EStdKeyNull ,    EStdKeyEquals  ,  EStdKeyEnter  ,EStdKeySquareBracketLeft,EStdKeySingleQuote,EStdKeyForwardSlash, EStdKeyFullStop  ,EStdKeyMenu,       // Column11
    72 	EStdKeyNull ,    EStdKeyNull    ,EStdKeyRightShift,   EStdKeyNull   ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column12
    73 	EStdKeyNull ,  EStdKeyBackspace ,EStdKeyDownArrow,EStdKeySquareBracketRight,EStdKeyUpArrow  , EStdKeyLeftArrow  ,    EStdKeySpace   ,EStdKeyRightArrow, // Column13
    74 	EStdKeyNull ,    EStdKeyNull    ,  EStdKeyNull   ,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull,       // Column14
    75 	EStdKeyNull ,    EStdKeyNull    ,  EStdKeyNull   ,   EStdKeyNull    ,      EStdKeyNull      ,   EStdKeyNull     ,    EStdKeyNull    ,EStdKeyNull        // Column15
    76 	};
    77 
    78 // EXAMPLE ONLY
    79 const TInt KFlagKeyPressed = 0x80;		// As an example, we'll assume the top bit indicates pressed/released
    80 
    81 // EXAMPLE ONLY
    82 const TKeyboard	KConfigKeyboardType = EKeyboard_Full;
    83 const TInt KConfigKeyboardDeviceKeys = 0;
    84 const TInt KConfigKeyboardAppsKeys = 0;
    85 //
    86 //
    87 _LIT(KLitKeyboard,"Keyboard");
    88 
    89 class DKeyboardTemplate : public DPowerHandler
    90 	{
    91 public:
    92 	DKeyboardTemplate();
    93 	TInt Create();
    94 public: // from DPowerHandler
    95 	void PowerUp();
    96 	void PowerDown(TPowerState);
    97 	TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
    98 	void KeyboardInfo(TKeyboardInfoV01& aInfo);
    99 	void KeyboardOn();
   100 	void KeyboardOff();
   101 	void HandleMsg(TMessageBase* aMsg);
   102 private:
   103 	static void Isr(TAny* aPtr);
   104 	static void EventDfcFn(TAny* aPtr);
   105 	void EventDfc();
   106 
   107 	void PowerUpDfc();
   108 	static void PowerUpDfcFn(TAny* aPtr);
   109 	void PowerDownDfc();
   110 	static void PowerDownDfcFn(TAny* aPtr);
   111 private:
   112 	void KeyboardPowerUp();
   113 	TUint GetKeyCode();
   114 	TBool IsKeyReady();
   115 public:
   116 	TDfcQue* iDfcQ;
   117 	TMessageQue iMsgQ;	
   118 	TDfc iPowerUpDfc;
   119 	TDfc iPowerDownDfc;	
   120 private:
   121 	TDfc iEventDfc;
   122 	TBool iKeyboardOn;
   123 	};
   124 
   125 LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
   126 	{
   127 	DKeyboardTemplate* pH=(DKeyboardTemplate*)aPtr;
   128 	return pH->HalFunction(aFunction,a1,a2);
   129 	}
   130 
   131 void rxMsg(TAny* aPtr)
   132 	{
   133 	DKeyboardTemplate& h=*(DKeyboardTemplate*)aPtr;
   134 	TMessageBase* pM=h.iMsgQ.iMessage;
   135 	if (pM)
   136 		h.HandleMsg(pM);
   137 	}
   138 
   139 //
   140 //	Keyboard class
   141 //
   142 DKeyboardTemplate::DKeyboardTemplate()
   143 	:	DPowerHandler(KLitKeyboard), 
   144 		iMsgQ(rxMsg,this,NULL,1),
   145 		iPowerUpDfc(PowerUpDfcFn,this,6),
   146 		iPowerDownDfc(PowerDownDfcFn,this,7),
   147 		iEventDfc(EventDfcFn,this,1)
   148 	{
   149 	}
   150 
   151 TInt DKeyboardTemplate::Create()
   152 //
   153 // Initialisation. Bind and enable the interrupt.
   154 //
   155 	{
   156 	iDfcQ=Kern::DfcQue0();
   157 
   158 	iKeyboardOn = EFalse;	
   159 		// install the HAL function
   160 	TInt r=Kern::AddHalEntry(EHalGroupKeyboard,halFunction,this);
   161 	if (r!=KErrNone)
   162 		return r;
   163 
   164 	iEventDfc.SetDfcQ(iDfcQ);
   165 	iPowerUpDfc.SetDfcQ(iDfcQ);
   166 	iPowerDownDfc.SetDfcQ(iDfcQ);
   167 	iMsgQ.SetDfcQ(iDfcQ);
   168 	iMsgQ.Receive();
   169 
   170 	// Bind the key event interrupt
   171 	r=Interrupt::Bind(KIntIdKeyboard,Isr,this);
   172 	if (r==KErrNone)
   173 		{
   174 		// install the power handler
   175 		Add();
   176 		KeyboardPowerUp();
   177 		}
   178 	return r;
   179 	}
   180 
   181 void DKeyboardTemplate::Isr(TAny* aPtr)
   182 	{
   183 	DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr;
   184 	Interrupt::Disable(KIntIdKeyboard);
   185 	k.iEventDfc.Add();
   186 	}
   187 
   188 void DKeyboardTemplate::EventDfcFn(TAny* aPtr)
   189 	{
   190 	((DKeyboardTemplate*)aPtr)->EventDfc();
   191 	}
   192 
   193 void DKeyboardTemplate::EventDfc()
   194 	{
   195 	__KTRACE_OPT(KHARDWARE,Kern::Printf("DKeyboardTemplate::EventDfc"));
   196 
   197 	TInt irq=NKern::DisableAllInterrupts();
   198 	while (IsKeyReady())						// while there are keys in the controller's output buffer
   199 		{
   200 		NKern::RestoreInterrupts(irq);
   201 		TRawEvent e;
   202 		TUint keyCode=GetKeyCode();				// Read keycodes from controller
   203 		__KTRACE_OPT(KHARDWARE,Kern::Printf("#%02x",keyCode));
   204 
   205 		//
   206 		// TO DO: (mandatory)
   207 		//
   208 		// Convert from hardware scancode to EPOC scancode and send the scancode as an event (key pressed or released)
   209 		// as per below EXAMPLE ONLY:
   210 		//
   211 		TUint bareCode=keyCode&~KFlagKeyPressed;
   212 		TUint8 stdKey=convertCode[bareCode];
   213 		if (keyCode&KFlagKeyPressed)
   214 			e.Set(TRawEvent::EKeyUp,stdKey,0);
   215 		else
   216 			e.Set(TRawEvent::EKeyDown,stdKey,0);
   217 		Kern::AddEvent(e);
   218 		NKern::Sleep(1);						// pause before reading more keycodes
   219 		irq=NKern::DisableAllInterrupts();
   220 		}
   221 	Interrupt::Enable(KIntIdKeyboard);
   222 	NKern::RestoreInterrupts(irq);
   223 	}
   224 
   225 TBool DKeyboardTemplate::IsKeyReady()
   226 	{
   227 	//
   228 	// TO DO: (mandatory)
   229 	//
   230 	// Return ETrue if the keyboard controller has a key event waiting to be read
   231 	//
   232 
   233 	return EFalse;	// EXAMPLE ONLY
   234 	}
   235 
   236 TUint DKeyboardTemplate::GetKeyCode()
   237 	{
   238 	//
   239 	// TO DO: (mandatory)
   240 	//
   241 	// Read and return the next available keycode from the keyboard controller
   242 	//
   243 
   244 	return 0;	// EXAMPLE ONLY
   245 	}
   246 
   247 void DKeyboardTemplate::PowerUpDfcFn(TAny* aPtr)
   248 	{
   249 	((DKeyboardTemplate*)aPtr)->PowerUpDfc();
   250 	}
   251 
   252 void DKeyboardTemplate::PowerDownDfcFn(TAny* aPtr)
   253 	{
   254 	((DKeyboardTemplate*)aPtr)->PowerDownDfc();
   255 	}
   256 
   257 
   258 void DKeyboardTemplate::KeyboardPowerUp()
   259 	{
   260 	__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardPowerUp()"));
   261 
   262 	iKeyboardOn = ETrue;
   263 
   264 	// Send key up events for EStdKeyOff (Fn+Esc) event 
   265 	TRawEvent e;
   266 	e.Set(TRawEvent::EKeyUp,EStdKeyEscape,0);
   267 	Kern::AddEvent(e);
   268 	e.Set(TRawEvent::EKeyUp,EStdKeyLeftFunc,0);
   269 	Kern::AddEvent(e);
   270 	}
   271 
   272 void DKeyboardTemplate::PowerUp()
   273 	{
   274 	iPowerUpDfc.Enque();	// schedules DFC to execute on this driver's thread
   275 	}
   276 
   277 void DKeyboardTemplate::PowerUpDfc()
   278 	{
   279 	__KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerUpDfc()"));
   280 	KeyboardOn();
   281 	PowerUpDone();		// must be called from a different thread than PowerUp()
   282 	}
   283 
   284 void DKeyboardTemplate::KeyboardOn()
   285 	{
   286 	__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOn() iKeyboardOn=%d", iKeyboardOn));
   287 
   288 	if (!iKeyboardOn)	// may be powered up from Power Manager or HAL
   289 		{
   290 		KeyboardPowerUp();
   291 		}
   292 	}
   293 
   294 void DKeyboardTemplate::PowerDown(TPowerState)
   295 	{
   296 	iPowerDownDfc.Enque();	// schedules DFC to execute on this driver's thread
   297 	}
   298 
   299 void DKeyboardTemplate::PowerDownDfc()
   300 	{
   301 	__KTRACE_OPT(KPOWER, Kern::Printf("DKeyboardTemplate::PowerDownDfc()"));
   302 	KeyboardOff();
   303 	PowerDownDone();		// must be called from a different thread than PowerDown()
   304 	}
   305 
   306 void DKeyboardTemplate::KeyboardOff()
   307 	{
   308 	__KTRACE_OPT(KPOWER,Kern::Printf("DKeyboardTemplate::KeyboardOff() iKeyboardOn=%d", iKeyboardOn));
   309 
   310 	if (iKeyboardOn)	// may have already been powered down by the HAL
   311 		{
   312 		iKeyboardOn = EFalse;
   313 		Interrupt::Disable(KIntIdKeyboard);
   314 		}
   315 	iEventDfc.Cancel();
   316 	}
   317 
   318 void DKeyboardTemplate::HandleMsg(TMessageBase* aMsg)
   319 	{
   320 	if (aMsg->iValue)
   321 		KeyboardOn();
   322 	else
   323 		KeyboardOff();
   324 	aMsg->Complete(KErrNone,ETrue);
   325 	}
   326 
   327 void DKeyboardTemplate::KeyboardInfo(TKeyboardInfoV01& aInfo)
   328 	{
   329 	__KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::KeyboardInfo"));
   330 
   331 	aInfo.iKeyboardType=KConfigKeyboardType;
   332 	aInfo.iDeviceKeys=KConfigKeyboardDeviceKeys;
   333 	aInfo.iAppsKeys=KConfigKeyboardAppsKeys;
   334 	}
   335 
   336 TInt DKeyboardTemplate::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
   337 	{
   338 	TInt r=KErrNone;
   339 	__KTRACE_OPT(KEXTENSION,Kern::Printf("DKeyboardTemplate::HalFunction %d", aFunction));
   340 	switch(aFunction)
   341 		{
   342 		case EKeyboardHalKeyboardInfo:
   343 			{
   344 			TPckgBuf<TKeyboardInfoV01> kPckg;
   345 			KeyboardInfo(kPckg());
   346 			Kern::InfoCopy(*(TDes8*)a1,kPckg);
   347 			break;
   348 			}
   349 		case EKeyboardHalSetKeyboardState:
   350 			{
   351 			if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EKeyboardHalSetKeyboardState")))
   352 				return KErrPermissionDenied;
   353 			if ((TBool)a1)
   354 				{
   355 				TThreadMessage& m=Kern::Message();
   356 				m.iValue = ETrue;
   357 				m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered up
   358 				}
   359 			else
   360 				{
   361 				TThreadMessage& m=Kern::Message();
   362 				m.iValue = EFalse;
   363 				m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered down
   364 				}
   365 			}
   366 			break;
   367 		case EKeyboardHalKeyboardState:
   368 			kumemput32(a1, &iKeyboardOn, sizeof(TBool));
   369 			break;
   370 		default:
   371 			r=KErrNotSupported;
   372 			break;
   373 		}
   374 	return r;
   375 	}
   376 
   377 DECLARE_STANDARD_EXTENSION()
   378 	{
   379 	__KTRACE_OPT(KEXTENSION,Kern::Printf("Starting keyboard driver"));
   380 
   381 	// create keyboard driver
   382 	TInt r=KErrNoMemory;
   383 	DKeyboardTemplate* pK=new DKeyboardTemplate;
   384 	if (pK)
   385 		r=pK->Create();
   386 
   387 	__KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));
   388 	return r;
   389 	}