navienginebsp/naviengine_assp/uart/vserialkeyb.cpp
changeset 0 5de814552237
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/navienginebsp/naviengine_assp/uart/vserialkeyb.cpp	Tue Sep 28 18:00:05 2010 +0100
@@ -0,0 +1,470 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+* naviengine_assp\uart\vserialkeyb.cpp
+* Serial keyboard driver
+*
+*/
+
+
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include <e32keys.h>
+#include <comm.h>
+#include <assp.h>
+#include "../naviengine_priv.h"
+#include "../naviengine.h"
+#include "uart16550_ne.h"
+#include "vserialkeyb.h"
+
+
+#define SHIFTED(x)   (0x8000|(x))
+#define ISSHIFTED(x) (0x8000&(x))
+#define FUNCED(x)    (0x4000|(x))
+#define ISFUNCED(x)  (0x4000&(x))
+#define CTRLED(x)    (0x2000|(x))
+#define ISCTRLED(x)  (0x2000&(x))
+#define STDKEY(x)    (0x1FFF&(x))
+
+/*
+ *  Definition of the converting table for the receive char
+ *  through the serial port.
+ *
+ */
+const TUint16 convertCodeSerial[] =
+{
+/*00*/	EStdKeyNull,
+/*01*/	EStdKeyHome,				// ^A
+/*02*/	EStdKeyLeftArrow,			// ^B
+/*03*/	EStdKeyEscape,				// ^C
+/*04*/	SHIFTED(EStdKeyDownArrow),	// ^D - move window down
+/*05*/	EStdKeyEnd,					// ^E
+/*06*/	EStdKeyRightArrow,			// ^F
+/*07*/	EStdKeyNull,
+/*08*/	EStdKeyBackspace,			// ^H - Reserved!
+/*09*/	EStdKeyTab,					// ^I - Reserved!
+/*0a*/	EStdKeyNull,
+/*0b*/	EStdKeyIncContrast,			// ^K
+/*0c*/	EStdKeyDecContrast,			// ^L
+/*0d*/	EStdKeyEnter,				// ^M - Reserved!
+/*0e*/	EStdKeyDownArrow,			// ^N
+/*0f*/	EStdKeyNull,				// ^O = instant death
+/*10*/	EStdKeyUpArrow,				// ^P
+/*11*/	CTRLED(EStdKeyLeftArrow),	// ^Q - make window narrower
+/*12*/	CTRLED(FUNCED('5')),		// ^R - rotate windows in text window server
+/*13*/	EStdKeyNull,
+/*14*/	CTRLED(EStdKeyDownArrow),	// ^T - make window taller
+/*15*/	SHIFTED(EStdKeyUpArrow),	// ^U - move window up
+/*16*/	EStdKeyNull,
+/*17*/	CTRLED(EStdKeyRightArrow),	// ^W - make window wider
+/*18*/	SHIFTED(EStdKeyRightArrow),	// ^X - move window right
+/*19*/	CTRLED(EStdKeyUpArrow),		// ^Y - make window shorter
+/*1a*/	SHIFTED(EStdKeyLeftArrow),	// ^Z - move window left
+/*1b*/	EStdKeyEscape,				// ^[ - Reserved!
+/*1c*/	EStdKeyNull,
+/*1d*/	EStdKeyNull,
+/*1e*/	EStdKeyNull,
+/*1f*/	EStdKeyNull,
+/*20*/	EStdKeySpace,
+/*21*/	SHIFTED('1'),		// !
+/*22*/	SHIFTED('2'),		// "
+/*23*/	EStdKeyHash,		// #
+/*24*/	SHIFTED('4'),		// $
+/*25*/	SHIFTED('5'),		// %
+/*26*/	SHIFTED('7'),		// &
+/*27*/	EStdKeySingleQuote,
+/*28*/	SHIFTED('9'),		// (
+/*29*/	SHIFTED('0'),		// )
+/*2a*/	SHIFTED('8'),		// *
+/*2b*/	SHIFTED(EStdKeyEquals),	// +
+/*2c*/	EStdKeyComma,
+/*2d*/	EStdKeyMinus,
+/*2e*/	EStdKeyFullStop,
+/*2f*/	EStdKeyForwardSlash,
+/*30*/	'0',
+/*31*/	'1',
+/*32*/	'2',
+/*33*/	'3',
+/*34*/	'4',
+/*35*/	'5',
+/*36*/	'6',
+/*37*/	'7',
+/*38*/	'8',
+/*39*/	'9',
+/*3a*/	SHIFTED(EStdKeySemiColon),	// :
+/*3b*/	EStdKeySemiColon,
+/*3c*/	SHIFTED(EStdKeyComma),		// <
+/*3d*/	EStdKeyEquals,
+/*3e*/	SHIFTED(EStdKeyFullStop),	// >
+/*3f*/	SHIFTED(EStdKeyForwardSlash),	// ?
+/*40*/	SHIFTED(EStdKeySingleQuote),	// @
+/*41*/	SHIFTED('A'),
+/*42*/	SHIFTED('B'),
+/*43*/	SHIFTED('C'),
+/*44*/	SHIFTED('D'),
+/*45*/	SHIFTED('E'),
+/*46*/	SHIFTED('F'),
+/*47*/	SHIFTED('G'),
+/*48*/	SHIFTED('H'),
+/*49*/	SHIFTED('I'),
+/*4a*/	SHIFTED('J'),
+/*4b*/	SHIFTED('K'),
+/*4c*/	SHIFTED('L'),
+/*4d*/	SHIFTED('M'),
+/*4e*/	SHIFTED('N'),
+/*4f*/	SHIFTED('O'),
+/*50*/	SHIFTED('P'),
+/*51*/	SHIFTED('Q'),
+/*52*/	SHIFTED('R'),
+/*53*/	SHIFTED('S'),
+/*54*/	SHIFTED('T'),
+/*55*/	SHIFTED('U'),
+/*56*/	SHIFTED('V'),
+/*57*/	SHIFTED('W'),
+/*58*/	SHIFTED('X'),
+/*59*/	SHIFTED('Y'),
+/*5a*/	SHIFTED('Z'),
+/*5b*/	EStdKeySquareBracketLeft,
+/*5c*/	EStdKeyBackSlash,
+/*5d*/	EStdKeySquareBracketRight,
+/*5e*/	SHIFTED('6'),			// ^
+/*5f*/	SHIFTED(EStdKeyMinus),	// _
+/*60*/	EStdKeyBacklightToggle,	// Actually `
+/*61*/	'A',
+/*62*/	'B',
+/*63*/	'C',
+/*64*/	'D',
+/*65*/	'E',
+/*66*/	'F',
+/*67*/	'G',
+/*68*/	'H',
+/*69*/	'I',
+/*6a*/	'J',
+/*6b*/	'K',
+/*6c*/	'L',
+/*6d*/	'M',
+/*6e*/	'N',
+/*6f*/	'O',
+/*70*/	'P',
+/*71*/	'Q',
+/*72*/	'R',
+/*73*/	'S',
+/*74*/	'T',
+/*75*/	'U',
+/*76*/	'V',
+/*77*/	'W',
+/*78*/	'X',
+/*79*/	'Y',
+/*7a*/	'Z',
+/*7b*/	SHIFTED(EStdKeySquareBracketLeft),
+/*7c*/	SHIFTED(EStdKeyBackSlash),
+/*7d*/	SHIFTED(EStdKeySquareBracketRight),
+/*7e*/	SHIFTED(EStdKeyHash),
+/*7f*/	EKeyDelete
+}; /* end of array - convertCodeSerial - */
+
+typedef struct
+	{
+	TUint8 seq[maxSeq+1];
+	TUint32 convertedCode;
+	} keyType;
+
+const keyType escapeCodes[] =
+{
+	// Three escape codes in a row that completes a sequence
+	{ {0x1b, 0x4f, 0x50, 0,    0,    0,}, EStdKeyMenu,                       }, // F1 gives menu key
+	{ {0x1b, 0x4f, 0x51, 0,    0,    0,}, EStdKeyF2,                         }, // F2
+	{ {0x1b, 0x4f, 0x52, 0,    0,    0,}, EStdKeyF3,                         }, // F3
+	{ {0x1b, 0x4f, 0x53, 0,    0,    0,}, EStdKeyF4,                         }, // F4
+	{ {0x1b, 0x4f, 0x74, 0,    0,    0,}, EStdKeyDevice3,                    }, // F5 gives S60 centre press
+	{ {0x1b, 0x4f, 0x75, 0,    0,    0,}, EStdKeyDevice0,                    }, // F6 gives S60 left softkey
+	{ {0x1b, 0x4f, 0x76, 0,    0,    0,}, EStdKeyDevice1,                    }, // F7 gives S60 right softkey
+	{ {0x1b, 0x4f, 0x6c, 0,    0,    0,}, EStdKeyApplication0,               }, // F8 gives S60 application softkey
+	{ {0x1b, 0x4f, 0x77, 0,    0,    0,}, EStdKeyF9,                         }, // F9
+	{ {0x1b, 0x4f, 0x78, 0,    0,    0,}, EStdKeyF10,                        }, // F10
+
+	{ {0x1b, 0x5b, 0x41, 0,    0,    0,}, EStdKeyUpArrow,                    }, // Arrow keys
+	{ {0x1b, 0x5b, 0x42, 0,    0,    0,}, EStdKeyDownArrow,                  }, // Arrow keys
+	{ {0x1b, 0x5b, 0x43, 0,    0,    0,}, EStdKeyRightArrow,                 }, // Arrow keys
+	{ {0x1b, 0x5b, 0x44, 0,    0,    0,}, EStdKeyLeftArrow,                  }, // Arrow keys
+
+	// Four escape codes in a row that completes a sequence
+	{ {0x1b, 0x5b, 0x31, 0x7e, 0,    0,}, EStdKeyHome,                       }, // Home key
+	{ {0x1b, 0x5b, 0x34, 0x7e, 0,    0,}, EStdKeyEnd,                        }, // End key
+	{ {0x1b, 0x5b, 0x35, 0x7e, 0,    0,}, EStdKeyPageUp,                     }, // Page Up key
+	{ {0x1b, 0x5b, 0x36, 0x7e, 0,    0,}, EStdKeyPageDown,                   }, // Page down key
+	{ {0x1b, 0x5b, 0x32, 0x7e, 0,    0,}, EStdKeyInsert,                     }, // Page down key
+
+	// Five escape codes in a row that completes a sequence
+	{ {0x1b, 0x5b, 0x32, 0x33, 0x7e, 0,}, EStdKeyF11,                        }, // F11
+	{ {0x1b, 0x5b, 0x32, 0x34, 0x7e, 0,}, EStdKeyF12,                        }, // F12
+
+	// end of table - should be all zeros
+    { {0,    0,    0,    0,    0,    0,}, 0,                                 }
+};
+
+TSerialKeyboard::TSerialKeyboard()
+				: iKeyDfc( KeyDfcFn, this, Kern::DfcQue0(), 1 ), iSeqNum(0)
+	{
+    for (TUint i=0; i<maxSeq; i++)
+        {
+        iCode[i]=0;
+        }
+	}
+ 
+TInt TSerialKeyboard::Create()
+	{
+//	__KTRACE_OPT(KBOOT,Kern::Printf(_L("+TKeyboardSerial::Init"))) ;
+	TUint base;
+	TUint baud;
+
+	iKeyboardPort = GetSerialPort(baud);
+
+	switch(iKeyboardPort)
+		{
+	case 1:		base=KHwBaseUart1; break;
+	case 2:		base=KHwBaseUart2; break;
+	default:	base=KHwBaseUart0;
+				iKeyboardPort = 0; //JTAG debug port, use port #0
+		}
+
+	__KTRACE_OPT(KBOOT,Kern::Printf("SERIAL KEYBOARD DRIVER: keyboard port=%d", iKeyboardPort ));
+
+	iUart = new T16550Uart;
+	if (iUart)
+		{
+		iUart->iBase = (TUint8*)base;
+		iUart->SetIER(0);
+		iUart->SetLCR(0);
+		iUart->SetFCR(0);
+		iUart->SetMCR(0);
+		}
+	else
+		return KErrNoMemory;
+	
+ 	iInterrupt=Interrupt::Bind(KIntIdUart0+iKeyboardPort,Isr,this);
+	if (iInterrupt<0)
+ 	{
+		delete iUart;
+		return iInterrupt;
+ 	}
+   
+	iUart->SetLCR(K16550LCR_Data8|K16550LCR_DLAB);
+	iUart->SetBaudRateDivisor((baud==230400) ? KBaudRateDiv_230400 : KBaudRateDiv_default);
+	iUart->SetLCR(K16550LCR_Data8);
+	iUart->SetFCR(K16550FCR_Enable|K16550FCR_RxReset|K16550FCR_TxReset|K16550FCR_RxTrig8);
+	iUart->SetIER(K16550IER_RDAI);// enable receiving data
+
+	Interrupt::Enable(iInterrupt);
+    
+	return KErrNone;
+	}
+
+
+void TSerialKeyboard::Isr( TAny* aPtr )
+	//
+	// Interrupt service routine. Called when we receive an interrupt
+	// on the IRQ line it is bound to. If it's a receive, queues DFC
+	// to post the event into the event queue.
+	//
+	{
+	TSerialKeyboard* self = (TSerialKeyboard*)aPtr;
+	T16550Uart& u=*(self->iUart);
+
+	TUint isr=u.ISR();
+	if (isr & K16550ISR_NotPending)
+		return;
+	isr&=K16550ISR_IntIdMask;
+ 
+	if (isr==K16550ISR_RDAI || isr==K16550ISR_RLSI)
+		{
+		__KTRACE_OPT(KEXTENSION,Kern::Printf("TSerialKeyboard::Isr:RHR"));
+		TUint ch=u.RxData();
+		if (ch==31)
+			__crash();	// CTRL-? = instant death
+		if (self->iSeqNum < maxSeq)
+			{
+			self->iCode[self->iSeqNum] = ch;
+			self->iSeqNum++;
+			self->iKeyDfc.Add();
+			Interrupt::Disable(self->iInterrupt); // Can only handle one char at a time
+			}
+		}
+	}
+	
+void TSerialKeyboard::KeyDfcFn( TAny* aPtr )
+	//
+	// DFC function. Just calls inline function KeyDfc()
+	//
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("TSerialKeyboard::KeyDfcFn"));
+	((TSerialKeyboard*)aPtr)->KeyDfc();
+	}
+
+void TSerialKeyboard::AddConvertedEvent(TUint aKey)
+	{
+	// split aKey into keycode and shift, func, ctrl status
+	TBool isShifted = ISSHIFTED(aKey);
+	TBool isFunced = ISFUNCED(aKey);
+	TBool isCtrled = ISCTRLED(aKey);
+	TUint8 stdKey = STDKEY(aKey);
+
+	// post it as a sequence of events
+	TRawEvent e;
+	if (isShifted)
+		{
+		e.Set(TRawEvent::EKeyDown,EStdKeyRightShift,0);
+		Kern::AddEvent(e);
+		}
+	if (isCtrled)
+		{
+		e.Set(TRawEvent::EKeyDown,EStdKeyLeftCtrl,0);
+		Kern::AddEvent(e);
+		}
+	if (isFunced)
+		{
+		e.Set(TRawEvent::EKeyDown,EStdKeyLeftFunc,0);
+		Kern::AddEvent(e);
+		}
+
+	e.Set(TRawEvent::EKeyDown,stdKey,0);
+	Kern::AddEvent(e);
+
+	e.Set(TRawEvent::EKeyUp,stdKey,0);
+	Kern::AddEvent(e);
+
+	if (isFunced)
+		{
+		e.Set(TRawEvent::EKeyUp,EStdKeyLeftFunc,0);
+		Kern::AddEvent(e);
+		}
+	if (isCtrled)
+		{
+		e.Set(TRawEvent::EKeyUp,EStdKeyLeftCtrl,0);
+		Kern::AddEvent(e);
+		}
+	if (isShifted)
+		{
+		e.Set(TRawEvent::EKeyUp,EStdKeyRightShift,0);
+		Kern::AddEvent(e);
+		}
+	}
+	
+void TSerialKeyboard::AddUnconvertedEvent(TUint aKey)
+	{
+	TUint16 convertedKey = convertCodeSerial[aKey];
+	AddConvertedEvent(convertedKey);
+	}
+	
+inline void TSerialKeyboard::KeyDfc()
+	//
+	// Processes received characters
+	//
+	{
+	__KTRACE_OPT(KEXTENSION, Kern::Printf("KEY: iSeqNum=%x, key=%x", iSeqNum, iCode[iSeqNum-1]));
+
+	switch (iSeqNum)
+		{
+	case 1:
+		if (iCode[0] != EEscapingStart)
+			{
+			// Unknown escape sequence - just pass chars as normal events
+			AddUnconvertedEvent(iCode[0]);
+			iSeqNum = 0;
+			}
+		break;
+	case 2:
+		if ((iCode[1] != EEscapingType1) && iCode[1] != EEscapingType2)
+			{
+			// Unknown escape sequence - just pass chars as normal events
+			AddUnconvertedEvent(iCode[0]);
+			AddUnconvertedEvent(iCode[1]);
+			iSeqNum = 0;
+			}
+		break;
+	case 3:
+	case 4:
+	case 5:
+		{
+		TUint escCodeindex = 0; // index into the escape code list
+		TUint seqIndex     = 0; // index into the current code sequence
+        TUint bestMatch    = 0; // keep a track of the best number of matches so far
+		while (escapeCodes[escCodeindex].seq[0] != 0)
+			{
+			for (seqIndex = 0; seqIndex<iSeqNum; seqIndex++)
+				{
+				if (iCode[seqIndex] != escapeCodes[escCodeindex].seq[seqIndex])
+					{
+					break; // out of for loop
+					}
+				}
+			if (seqIndex > bestMatch)
+				{
+				bestMatch = seqIndex;
+				}
+			if (escapeCodes[escCodeindex].seq[seqIndex] == 0)
+				{
+				AddConvertedEvent(escapeCodes[escCodeindex].convertedCode);
+				iSeqNum = 0;
+				break; // out of while loop
+				}
+			escCodeindex++;
+			}
+
+		if (  (bestMatch < iSeqNum) // if we couldn't match all numbers in the sequence so far, this must not be a valid sequence
+		   || (iSeqNum == maxSeq)   // if we reached the max number of codes in a sequence, this must also not be a valid sequence
+		   )
+			{
+			if (escapeCodes[escCodeindex].seq[0] == 0)
+				{
+				// Unknown escape sequence - just pass chars as normal events
+				for (TUint i=0; i < iSeqNum; i++)
+					{
+					AddUnconvertedEvent(iCode[i]);
+					}
+				}
+			iSeqNum = 0;
+			}
+		}
+		break;
+	default:
+		// Should never reach here!
+		iSeqNum = 0;
+		break;
+		};
+	Interrupt::Enable(iInterrupt); // Can handle new chars now
+	} /* end of function - KeyDfc - */
+
+//
+// Kernel Extension entry point
+//
+DECLARE_STANDARD_EXTENSION()
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("Starting keyboard driver"));
+
+	// create keyboard driver
+	TInt r=KErrNoMemory;
+	TSerialKeyboard* keyboard = new TSerialKeyboard;
+	if ( keyboard )
+		{
+		r=keyboard->Create();
+		}
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r));
+	return r;
+	}