diff -r 000000000000 -r 6663340f3fc9 omap3530/shared/serialkeyb/serialkeyboard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/shared/serialkeyb/serialkeyboard.cpp Thu Oct 15 12:59:54 2009 +0100 @@ -0,0 +1,414 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// omap3530/shared/serialkeyb/serialkeyboard.mmp +// Simple serial keyboard implementation for Beagle baseport +// + +#include +#include +#include +#include +//#include + +const TInt KMagicCrashValue = 15; + + +#define SHIFTED(x) (0x8000|(x)) +#define ISSHIFTED(x) (0x8000&(x)) +#define CTRLED(x) (0x2000|(x)) +#define ISCTRL(x) (0x2000&(x)) +#define FUNCED(x) (0x4000|(x)) +#define ISFUNC(x) (0x4000&(x)) +#define STDKEY(x) (0x1FFF&(x)) + +static const TUint16 KScanCode[] = + { + /*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 + }; + +static const TUint16 KEscapedScanCode[] = + { + EStdKeyUpArrow, + EStdKeyDownArrow, + EStdKeyRightArrow, + EStdKeyLeftArrow + }; + +const TUint8 KEscapeChar = 0x1b; +const TUint8 KEscapeBase = 0x41; +const TUint8 KEscapeCount = sizeof(KEscapedScanCode) / sizeof(KEscapedScanCode[0]); +const TUint16 KEscapeScanCode = EStdKeyEscape; + +NONSHARABLE_CLASS(TSerialKeyboard) : public DBase + { +public: + inline TSerialKeyboard(); + TInt Create(); + +private: + static void UartIsr( TAny* aParam ); + static void AddKeyDfc( TAny* aParam ); + void AddKey( TUint aKey ); + + +private: + enum TState + { + ENormal, + EEscaping1, + EEscaping2 + }; + + TDfc iAddKeyDfc; + Omap3530Uart::TUart iUart; + TUint iPrmClientId; + TState iState : 8; + TUint8 iKey; + }; + +inline TSerialKeyboard::TSerialKeyboard() +: iAddKeyDfc( AddKeyDfc, this, Kern::DfcQue0(), 1 ), + iUart( Omap3530Assp::DebugPortNumber() ), + iState( ENormal ) + { + // Convert the scan rate from milliseconds to nanokernel ticks (normally 1/64 of a second) + } + +TInt TSerialKeyboard::Create() + { + TInt r = KErrNone; + + const Omap3530Uart::TUartNumber portNumber( Omap3530Assp::DebugPortNumber() ); + + if( portNumber >= 0 ) + { + // Register with the power resource manager + _LIT( KName, "serkey" ); + /*r = PowerResourceManager::RegisterClient( iPrmClientId, KName ); + if( r != KErrNone ) + { + return r; + }*/ + + __KTRACE_OPT(KBOOT,Kern::Printf("+TSerialKeyboardl::Create:PRM client ID=%x", iPrmClientId )) ; + Kern::Printf("+TSerialKeyboardl::Create:PRM client ID=%x", iPrmClientId ); + + r = Interrupt::Bind( iUart.InterruptId(), UartIsr, this ); + if ( r < 0 ) + { + return r; + } + + // Ask power resource manager to turn on clocks to the UART + // (this could take some time but we're not in any hurry) + /*r = PowerResourceManager::ChangeResourceState( iPrmClientId, iUart.PrmFunctionClk(), Prcm::EClkOn ); + if( KErrNone != r ) + { + return r; + }*/ + + /*r = PowerResourceManager::ChangeResourceState( iPrmClientId, iUart.PrmInterfaceClk(), Prcm::EClkOn ); + if( KErrNone != r ) + { + return r; + }*/ + + // We can assume that the debug output code has already initialized the UART, we just need to prepare it for RX + iUart.EnableFifo( Omap3530Uart::TUart::EEnabled, Omap3530Uart::TUart::ETriggerUnchanged, Omap3530Uart::TUart::ETrigger8 ); + iUart.EnableInterrupt( Omap3530Uart::TUart::EIntRhr ); + + Interrupt::Enable( iUart.InterruptId() ); + } + + return r; + } + +void TSerialKeyboard::UartIsr( TAny* aParam ) + { + TSerialKeyboard* self = reinterpret_cast( aParam ); + + const TUint iir = Omap3530Uart::IIR::iMem.Read( self->iUart ); + + if ( 0 == (iir bitand Omap3530Uart::IIR::IT_PENDING::KMask) ) + { + const TUint pending = iir bitand Omap3530Uart::IIR::IT_TYPE::KFieldMask; + + // Although the TI datasheet descrivwed IT_TYPE as being an enumerated priority-decoded interrupt + // it appears to actually be a bitmask of active interrupt sources + if ( (pending bitand Omap3530Uart::IIR::IT_TYPE::ERHR) || (pending bitand Omap3530Uart::IIR::IT_TYPE::ERxLineStatus) ) + { + TUint byte = self->iUart.Read(); + + if( KMagicCrashValue == byte ) + { + Kern::Fault( "SERKEY-FORCED", 0 ); + } + else + { + self->iKey = byte; + self->iAddKeyDfc.Add(); + Interrupt::Disable( self->iUart.InterruptId() ); + } + } + } + } + +void TSerialKeyboard::AddKeyDfc( TAny* aParam ) + { + TSerialKeyboard* self = reinterpret_cast( aParam ); + + switch ( self->iState ) + { + case ENormal: + if ( self->iKey == KEscapeChar ) + { + self->iState = EEscaping1; + } + else + { + self->AddKey( KScanCode[ self->iKey ] ); + } + break; + + case EEscaping1: + if ( self->iKey == KEscapeChar ) + { + self->iState = EEscaping2; + } + else + { + self->AddKey( KEscapeScanCode ); + self->AddKey( KScanCode[ self->iKey ] ); + self->iState = ENormal; + } + break; + + case EEscaping2: + { + TInt index = self->iKey - KEscapeBase; + + if ( (index >= 0) && (index < KEscapeCount) ) + { + self->AddKey( KEscapedScanCode[ index ] ); + } + else + { + self->AddKey( KEscapeScanCode ); + self->AddKey( KScanCode[ self->iKey ] ); + } + self->iState = ENormal; + } + break; + + default: + self->iState = ENormal; + break; + }; + + Interrupt::Enable( self->iUart.InterruptId() ); + } + +void TSerialKeyboard::AddKey( TUint aKey ) + { + const TBool shifted = ISSHIFTED(aKey); + const TBool ctrl = ISCTRL(aKey); + const TBool func = ISFUNC(aKey); + const TUint8 stdKey = STDKEY(aKey); + + TRawEvent e; + + if ( func ) + { + e.Set( TRawEvent::EKeyDown, EStdKeyRightFunc, 0 ); + Kern::AddEvent( e ); + } + + if ( ctrl ) + { + e.Set( TRawEvent::EKeyDown, EStdKeyRightCtrl, 0 ); + Kern::AddEvent( e ); + } + + if ( shifted ) + { + e.Set( TRawEvent::EKeyDown, EStdKeyRightShift, 0 ); + Kern::AddEvent( e ); + } + + e.Set( TRawEvent::EKeyDown, stdKey, 0 ); + Kern::AddEvent( e ); + e.Set( TRawEvent::EKeyUp, stdKey, 0 ); + Kern::AddEvent( e ); + + if ( shifted ) + { + e.Set( TRawEvent::EKeyUp, EStdKeyRightShift, 0 ); + Kern::AddEvent( e ); + } + + if ( ctrl ) + { + e.Set( TRawEvent::EKeyUp, EStdKeyRightCtrl, 0 ); + Kern::AddEvent( e ); + } + + if ( func ) + { + e.Set( TRawEvent::EKeyUp, EStdKeyRightFunc, 0 ); + Kern::AddEvent( e ); + } + } + + +DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting serial keyboard driver")); + + TInt r = KErrNoMemory; + TSerialKeyboard* keyboard = new TSerialKeyboard; + if ( keyboard ) + { + r = keyboard->Create(); + } + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + }