baseport/src/cedar/generic/base/syborg/keyboard/syborg_keyboard.cpp
changeset 0 ffa851df0825
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/src/cedar/generic/base/syborg/keyboard/syborg_keyboard.cpp	Fri Jul 31 14:43:15 2009 +0100
@@ -0,0 +1,227 @@
+/*
+* Copyright (c) 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: Minimalistic keyboard driver
+*
+*/
+
+//#define DEBUG
+
+#include "syborg_keyboard.h"
+
+LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
+{
+  DKeyboardPs2Soc* pH=(DKeyboardPs2Soc*)aPtr;
+  return pH->HalFunction(aFunction,a1,a2);
+}
+
+void rxMsg(TAny* aPtr)
+{
+  DKeyboardPs2Soc& h=*(DKeyboardPs2Soc*)aPtr;
+  TMessageBase* pM=h.iMsgQ.iMessage;
+  if (pM)
+	h.HandleMsg(pM);
+}
+
+TInt DKeyboardPs2Soc::FifoPop(void)
+{
+  TInt val = iKeyFifo[iFifoPos];
+  iFifoPos++;
+  iFifoCount--;
+  
+  if (iFifoPos == FIFO_SIZE)
+	iFifoPos = 0;
+
+  return val;
+}
+
+void DKeyboardPs2Soc::FifoPush(TInt val)
+{
+  TInt slot;
+
+  if (iFifoCount == FIFO_SIZE)
+	return;
+  
+  slot = iFifoPos + iFifoCount;
+  if (slot >= FIFO_SIZE)
+	slot -= FIFO_SIZE;
+  iKeyFifo[slot] = val;
+  iFifoCount++;
+}
+
+void DKeyboardPs2Soc::Isr(TAny* aPtr)
+{
+  __DEBUG_PRINT("DKeyboardPs2Soc::Isr");
+  DKeyboardPs2Soc& k = *(DKeyboardPs2Soc*)aPtr;
+
+  // Is now auto-clearing
+  while(ReadReg(KHwBaseKmiKeyboard, KBD_FIFO_COUNT)!=0)
+	k.FifoPush(ReadReg(KHwBaseKmiKeyboard, KBD_DATA));
+  
+  //WriteReg(KHwBaseKmiKeyboard,KBD_CLEAR_INT, 0);
+  Interrupt::Clear(EIntKeyboard); 
+  k.iRxDfc.Add();
+}
+
+DKeyboardPs2Soc::DKeyboardPs2Soc()
+  :	DPowerHandler(KLitKeyboard),
+	iRxDfc(RxDfc,this,Kern::DfcQue0(),1),
+	iMsgQ(rxMsg,this,NULL,1)
+{
+  iKeyboardOn = ETrue;
+  iFifoPos = 0;
+  iFifoCount = 0;
+}
+
+TInt DKeyboardPs2Soc::Create()
+{
+  __DEBUG_PRINT("DKeyboardPs2Soc::Create");
+
+  TInt r=KErrNone;
+  iDfcQ=Kern::DfcQue0();
+
+  iFifoPos = iFifoCount = 0;
+
+  r=Kern::AddHalEntry(EHalGroupKeyboard,halFunction,this);
+  if (r!=KErrNone)
+	return r;
+
+  iMsgQ.SetDfcQ(iDfcQ);
+  iMsgQ.Receive();
+
+  r=Interrupt::Bind(EIntKeyboard,Isr,this);
+  if (r==KErrNone) {
+	Add();
+	KeyboardOn();
+  }
+  return r;
+}
+
+void DKeyboardPs2Soc::PowerUp()
+{
+  PowerUpDone();
+}
+
+void DKeyboardPs2Soc::PowerDown(TPowerState)
+{
+  PowerDownDone();
+}
+
+void DKeyboardPs2Soc::KeyboardOn()
+{
+  __DEBUG_PRINT("DKeyboardPs2Soc::KeyboardOn");
+  TInt reg = ReadReg(KHwBaseKmiKeyboard,KBD_ID);
+  
+  Interrupt::Enable(EIntKeyboard);
+  WriteReg(KHwBaseKmiKeyboard,KBD_INT_ENABLE,1);
+}
+
+void DKeyboardPs2Soc::KeyboardOff()
+{
+  __DEBUG_PRINT("DKeyboardPs2Soc::KeyboardOff");
+  Interrupt::Disable(EIntKeyboard);
+  WriteReg(KHwBaseKmiKeyboard,KBD_INT_ENABLE,0);
+}
+
+void DKeyboardPs2Soc::HandleMsg(TMessageBase* aMsg)
+{
+  __DEBUG_PRINT("DKeyboardPs2Soc::HandleMsg");
+  if (aMsg->iValue)
+	KeyboardOn();
+  else
+	KeyboardOff();
+  aMsg->Complete(KErrNone,ETrue);
+}
+
+void DKeyboardPs2Soc::KeyboardInfo(TKeyboardInfoV01& aInfo)
+{
+  aInfo.iKeyboardType=KConfigKeyboardType;
+  aInfo.iDeviceKeys=KConfigKeyboardDeviceKeys;
+  aInfo.iAppsKeys=KConfigKeyboardAppsKeys;
+}
+
+TInt DKeyboardPs2Soc::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
+{
+  TInt r=KErrNone;
+
+  __DEBUG_PRINT("DKeyboardPs2Soc::HalFunction");
+  switch(aFunction)
+	{
+	case EKeyboardHalKeyboardInfo:
+	  {
+		TPckgBuf<TKeyboardInfoV01> kPckg;
+		KeyboardInfo(kPckg());
+		Kern::InfoCopy(*(TDes8*)a1,kPckg);
+		break;
+	  }
+	  // UIKLAF Silent running/power management
+	case EKeyboardHalSetKeyboardState:
+	  {
+		if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EKeyboardHalSetKeyboardState")))
+		  return KErrPermissionDenied;
+		if ((TBool)a1)
+		  {
+			TThreadMessage& m=Kern::Message();
+			m.iValue = ETrue;
+			m.SendReceive(&iMsgQ);
+		  }
+		else
+		  {
+			TThreadMessage& m=Kern::Message();
+			m.iValue = EFalse;
+			m.SendReceive(&iMsgQ);
+		  }
+	  }
+	  break;
+	case EKeyboardHalKeyboardState:
+	  kumemput32(a1, &iKeyboardOn, sizeof(TBool));
+	  break;
+	default:
+	  r=KErrNotSupported;
+	  break;
+	}
+  return r;
+}
+
+void DKeyboardPs2Soc::RxDfc(TAny* aPtr)
+{
+  TRawEvent e;
+  DKeyboardPs2Soc& k = *(DKeyboardPs2Soc*)aPtr;
+
+  while(k.iFifoCount>0) {
+	int keycode = k.FifoPop();
+	int dwn = (keycode & 0x80000000) ? 0 : 1;
+	__DEBUG_PRINT("DKeyboardPs2Soc::RxDfc %d %d", keycode, dwn);
+  
+	keycode &= ~(0x80000000);	
+	if (dwn) {
+	  __DEBUG_PRINT("kbd EKeyDown:%d",keycode);
+	  e.Set(TRawEvent::EKeyDown,KConvertCode[keycode],0);
+	}
+	else {
+	  __DEBUG_PRINT("kbd EKeyUp:%d",keycode);
+	  e.Set(TRawEvent::EKeyUp,KConvertCode[keycode],0);
+	}
+	Kern::AddEvent(e);
+  }
+}
+
+DECLARE_STANDARD_EXTENSION()
+{
+  TInt r=KErrNoMemory;
+  DKeyboardPs2Soc* pK=new DKeyboardPs2Soc;
+  if (pK)
+	r=pK->Create();
+  __KTRACE_OPT(KEXTENSION,__DEBUG_PRINT("Returns %d",r));
+  return r;
+}