Better keyboard implementation

This commit is contained in:
José Pedro 2016-07-18 02:42:33 +01:00
parent 2408319b41
commit eede1e6675
19 changed files with 320 additions and 284 deletions

View file

@ -97,11 +97,7 @@
<Compile Include="BlockDevice\MBR.cs" />
<Compile Include="BlockDevice\Partition.cs" />
<Compile Include="Bootstrap.cs" />
<Compile Include="ConsoleKeyEx.cs" />
<Compile Include="ConsoleKeyExExtensions.cs" />
<Compile Include="DebugTextScreen.cs" />
<Compile Include="KeyEvent.cs" />
<Compile Include="KeyMapping.cs" />
<Compile Include="PS2Keyboard.cs" />
<Compile Include="Device.cs" />
<Compile Include="Drivers\PCI\Audio\ES1370\Components\DACak4531.cs" />
@ -127,7 +123,7 @@
<Compile Include="Drivers\VBEDriver.cs" />
<Compile Include="Drivers\VGAScreen.cs" />
<Compile Include="Global.cs" />
<Compile Include="Keyboard.cs" />
<Compile Include="KeyboardBase.cs" />
<Compile Include="BlockDevice\AtaPio.cs" />
<Compile Include="Mouse.cs" />
<Compile Include="NetworkDevice.cs" />
@ -145,7 +141,6 @@
<Compile Include="Power.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RTC.cs" />
<Compile Include="ScanMapBase.cs" />
<Compile Include="TextScreen.cs" />
<Compile Include="Drivers\USB\USBHost.cs" />
<Compile Include="Drivers\USB\USBHostOHCI.cs" />

View file

@ -10,29 +10,29 @@ namespace Cosmos.HAL
{
public static readonly Debugger mDebugger = new Debugger("HAL", "Global");
public static Keyboard Keyboard;
//public static Keyboard Keyboard;
public static bool NumLock
{
get { return _numLock; }
set { _numLock = value; Keyboard?.UpdateLeds(); }
}
//public static bool NumLock
//{
// get { return _numLock; }
// set { _numLock = value; Keyboard?.UpdateLeds(); }
//}
public static bool CapsLock
{
get { return _capsLock; }
set { _capsLock = value; Keyboard?.UpdateLeds(); }
}
//public static bool CapsLock
//{
// get { return _capsLock; }
// set { _capsLock = value; Keyboard?.UpdateLeds(); }
//}
public static bool ScrollLock
{
get { return _scrollLock; }
set
{
_scrollLock = value;
Keyboard?.UpdateLeds();
}
}
//public static bool ScrollLock
//{
// get { return _scrollLock; }
// set
// {
// _scrollLock = value;
// Keyboard?.UpdateLeds();
// }
//}
//static public PIT PIT = new PIT();
// Must be static init, other static inits rely on it not being null
@ -117,21 +117,13 @@ namespace Cosmos.HAL
//PCI.Setup();
}
static public void Init(TextScreenBase textScreen, Keyboard keyboard)
static public void Init(TextScreenBase textScreen)
{
if (textScreen != null)
{
TextScreen = textScreen;
}
if (keyboard == null)
{
mDebugger.Send("No keyboard specified!");
throw new SystemException("No keyboard specified!");
}
else
{
Keyboard = keyboard;
}
mDebugger.Send("Before Core.Global.Init");
Core.Global.Init();
mDebugger.Send("Static Devices");

View file

@ -1,94 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.Debug.Kernel;
namespace Cosmos.HAL {
public abstract class Keyboard : Device {
protected Keyboard(ScanMapBase scanMap)
{
if (mQueuedKeys != null)
{
Debugger.DoSend("Skipping creation of key queue!");
}
mQueuedKeys = new Queue<KeyEvent>();
Debugger.DoSend("mQueuedKeys created");
SetKeyLayout(scanMap);
Debugger.DoSend("Keylayout set");
Initialize();
Debugger.DoSend("Initialized");
UpdateLeds();
Debugger.DoSend("Leds updated");
}
/// <summary>
/// Initialize the device. Happens before the interrupt is registered, ie before the class is being used.
/// </summary>
protected abstract void Initialize();
public ScanMapBase KeyLayout { get; private set; }
public void SetKeyLayout(ScanMapBase layout)
{
KeyLayout = layout;
}
/// <summary>
/// Allow faking scancodes. Used for test kernels
/// </summary>
internal void HandleFakeScanCode(byte aScancode, bool aReleased)
{
HandleScancode(aScancode, aReleased);
}
public abstract void UpdateLeds();
protected abstract void HandleScancode(byte aScancode, bool aReleased);
private static Queue<KeyEvent> mQueuedKeys;
protected void Enqueue(KeyEvent aKey)
{
mQueuedKeys.Enqueue(aKey);
}
public bool TryReadKey(out KeyEvent oKey)
{
if (mQueuedKeys.Count > 0)
{
oKey = mQueuedKeys.Dequeue();
return true;
}
oKey = default(KeyEvent);
return false;
}
public KeyEvent ReadKey()
{
while (mQueuedKeys.Count == 0)
{
Core.Global.CPU.Halt();
}
return mQueuedKeys.Dequeue();
}
public bool ShiftPressed
{
get;
protected set;
}
public bool ControlPressed
{
get;
protected set;
}
public bool AltPressed
{
get;
protected set;
}
}
}

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.Debug.Kernel;
namespace Cosmos.HAL
{
public abstract class KeyboardBase : Device
{
protected KeyboardBase()
{
Debugger.DoSend("mQueuedKeys created");
Debugger.DoSend("Keylayout set");
Initialize();
Debugger.DoSend("Initialized");
UpdateLeds();
Debugger.DoSend("Leds updated");
}
/// <summary>
/// Initialize the device. Happens before the interrupt is registered, ie before the class is being used.
/// </summary>
protected abstract void Initialize();
public abstract void UpdateLeds();
public delegate void KeyPressedEventHandler(byte ScanCode, bool Released);
public KeyPressedEventHandler OnKeyPressed;
public void WaitForKey()
{
Core.Global.CPU.Halt();
}
}
}

View file

@ -6,12 +6,13 @@ using Cosmos.Debug.Kernel;
namespace Cosmos.HAL
{
public class PS2Keyboard : Keyboard
public class PS2Keyboard : KeyboardBase
{
protected Core.IOGroup.Keyboard IO = Core.Global.BaseIOGroups.Keyboard;
public PS2Keyboard(ScanMapBase scanMap): base(scanMap)
public PS2Keyboard() : base()
{
}
protected override void Initialize()
@ -27,7 +28,7 @@ namespace Cosmos.HAL
{
xScanCode = (byte)(xScanCode ^ 0x80);
}
HandleScancode(xScanCode, xReleased);
OnKeyPressed?.Invoke(xScanCode, xReleased);
}
public override void UpdateLeds()
@ -43,78 +44,5 @@ namespace Cosmos.HAL
//{
//}
}
protected override void HandleScancode(byte aScancode, bool aReleased)
{
byte key = aScancode;
if (key == 0x3A && !aReleased)
{
// caps lock
Global.CapsLock = !Global.CapsLock;
UpdateLeds();
}
else if (key == 0x45 && !aReleased)
{
// num lock
Global.NumLock = !Global.NumLock;
UpdateLeds();
}
else if (key == 0x46 && !aReleased)
{
// scroll lock
Global.ScrollLock = !Global.ScrollLock;
UpdateLeds();
}
else
switch (key)
{
case 0x1D:
{
ControlPressed = !aReleased;
break;
}
case 0x2A:
case 0x36:
{
ShiftPressed = !aReleased;
break;
}
case 0x38:
{
AltPressed = !aReleased;
break;
}
default:
{
if (ControlPressed && AltPressed && (key == 0x53))
{
Console.WriteLine("Detected Ctrl-Alt-Delete! Rebooting System...");
Core.Global.CPU.Reboot();
}
if (!aReleased)
{
KeyEvent keyInfo;
if (GetKey(key, aReleased, out keyInfo))
{
Enqueue(keyInfo);
}
}
break;
}
}
}
public bool GetKey(byte aScancode, bool released, out KeyEvent keyInfo)
{
if (KeyLayout == null)
{
Debugger.DoSend("No KeyLayout");
}
keyInfo = KeyLayout.ConvertScanCode(aScancode, ControlPressed, ShiftPressed, AltPressed, Global.NumLock, Global.CapsLock, Global.ScrollLock);
return keyInfo != null;
}
}
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using Cosmos.HAL;
using Encoding = System.Text.Encoding;
using Plug = Cosmos.IL2CPU.Plugs.PlugAttribute;
@ -385,7 +384,7 @@ namespace Cosmos.System.Plugs.System
// TODO special cases, if needed, that returns -1
KeyEvent xResult;
if (HAL.Global.Keyboard.TryReadKey(out xResult))
if (Global.Keyboard.TryReadKey(out xResult))
{
return xResult.KeyChar;
}
@ -399,7 +398,7 @@ namespace Cosmos.System.Plugs.System
public static ConsoleKeyInfo ReadKey(Boolean intercept)
{
var key = Cosmos.HAL.Global.Keyboard.ReadKey();
var key = Global.Keyboard.ReadKey();
if (false == intercept && key.KeyChar != '\0')
{
Write(key.KeyChar);
@ -420,7 +419,7 @@ namespace Cosmos.System.Plugs.System
KeyEvent current;
int currentCount = 0;
while ((current = HAL.Global.Keyboard.ReadKey()).Key != ConsoleKeyEx.Enter)
while ((current = Global.Keyboard.ReadKey()).Key != ConsoleKeyEx.Enter)
{
if (current.Key == ConsoleKeyEx.NumEnter) break;
//Check for "special" keys

View file

@ -101,6 +101,12 @@
<Compile Include="FileSystem\VFS\VFSManager.cs" />
<Compile Include="Global.cs" />
<Compile Include="Kernel.cs" />
<Compile Include="Keyboard\ConsoleKeyEx.cs" />
<Compile Include="Keyboard\ConsoleKeyExExtensions.cs" />
<Compile Include="Keyboard\Keyboard.cs" />
<Compile Include="Keyboard\KeyEvent.cs" />
<Compile Include="Keyboard\KeyMapping.cs" />
<Compile Include="Keyboard\ScanMapBase.cs" />
<Compile Include="MathEx.cs" />
<Compile Include="Network\ARP\ARPCache.cs" />
<Compile Include="Network\ARP\ARPPacket.cs" />
@ -118,9 +124,8 @@
<Compile Include="Network\UdpClient.cs" />
<Compile Include="Power.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScanMaps\FR_Standard.cs" />
<Compile Include="ScanMaps\ScanMap.cs" />
<Compile Include="ScanMaps\US_Standard.cs" />
<Compile Include="Keyboard\ScanMaps\FR_Standard.cs" />
<Compile Include="Keyboard\ScanMaps\US_Standard.cs" />
<Compile Include="TestingHelpers.cs" />
<Compile Include="Graphics\VBEScreen.cs" />
<Compile Include="Graphics\VGAScreen.cs" />

View file

@ -19,22 +19,24 @@ namespace Cosmos.System
public static Console Console = new Console(null);
public static Keyboard Keyboard;
public static bool NumLock
{
get { return HAL.Global.NumLock; }
set { HAL.Global.NumLock = value; }
get { return Keyboard.NumLock; }
set { Keyboard.NumLock = value; }
}
public static bool CapsLock
{
get { return HAL.Global.CapsLock; }
set { HAL.Global.CapsLock = value; }
get { return Keyboard.CapsLock; }
set { Keyboard.CapsLock = value; }
}
public static bool ScrollLock
{
get { return HAL.Global.ScrollLock; }
set { HAL.Global.ScrollLock = value; }
get { return Keyboard.ScrollLock; }
set { Keyboard.ScrollLock = value; }
}
public static void Init(TextScreenBase textScreen, Keyboard keyboard)
@ -47,8 +49,19 @@ namespace Cosmos.System
Console = new Console(textScreen);
}
mDebugger.Send("Creating Keyboard");
if(keyboard != null)
{
Keyboard = keyboard;
}
else
{
Debugger.DoSend("Keyboard is null. Using default Keyboard: PS2Keyboard with US_Standard scan map.");
Keyboard = new Keyboard(new PS2Keyboard(), new ScanMaps.US_Standard());
}
mDebugger.Send("HW Init");
HAL.Global.Init(textScreen, keyboard);
HAL.Global.Init(textScreen);
NumLock = false;
CapsLock = false;
ScrollLock = false;
@ -57,9 +70,9 @@ namespace Cosmos.System
public static void ChangeKeyLayout(ScanMapBase scanMap)
{
if (scanMap != null && HAL.Global.Keyboard != null)
if (scanMap != null && Keyboard != null)
{
HAL.Global.Keyboard.SetKeyLayout(scanMap);
Keyboard.SetKeyLayout(scanMap);
}
}
}

View file

@ -20,30 +20,7 @@ namespace Cosmos.System
// Set to signal stopped
protected bool mStopped = false;
protected ScanMap mKeyboardScanMap = new US_Standard();
public ScanMap KeyboardScanMap
{
get
{
if (mKeyboardScanMap == null)
{
mKeyboardScanMap = new US_Standard();
}
return mKeyboardScanMap;
}
set
{
if (value != null)
{
mKeyboardScanMap = value;
Global.ChangeKeyLayout(mKeyboardScanMap);
}
return;
}
}
protected ScanMapBase DefaultKeyboardScanMap = new US_Standard();
protected virtual TextScreenBase GetTextScreen()
{
@ -51,6 +28,16 @@ namespace Cosmos.System
return null;
}
protected ScanMapBase GetKeyboardScanMap()
{
return Global.Keyboard.GetKeyLayout();
}
protected void SetKeyboardScanMap(ScanMapBase ScanMap)
{
Global.Keyboard.SetKeyLayout(ScanMap);
}
/// <summary>
/// Start the system up using the properties for configuration.
/// </summary>
@ -75,7 +62,7 @@ namespace Cosmos.System
HAL.Bootstrap.Init();
Global.mDebugger.Send("Global Init");
Global.Init(GetTextScreen(), new PS2Keyboard(KeyboardScanMap));
Global.Init(GetTextScreen(), new Keyboard(new PS2Keyboard(), DefaultKeyboardScanMap));
// Provide the user with a clear screen if they requested it
if (ClearScreen)

View file

@ -1,4 +1,4 @@
namespace Cosmos.HAL
namespace Cosmos.System
{
public enum ConsoleKeyEx
{
@ -53,7 +53,7 @@ namespace Cosmos.HAL
LBracket,
RBracket,
Enter,
CapsLock,
A,
S,
@ -130,4 +130,4 @@ namespace Cosmos.HAL
Sleep,
Wake
}
}
}

View file

@ -1,6 +1,6 @@
using System;
namespace Cosmos.HAL
namespace Cosmos.System
{
public static class ConsoleKeyExExtensions
{
@ -176,4 +176,4 @@ namespace Cosmos.HAL
}
}
}
}
}

View file

@ -1,6 +1,6 @@
using System;
namespace Cosmos.HAL
namespace Cosmos.System
{
public class KeyEvent
{
@ -61,4 +61,4 @@ namespace Cosmos.HAL
this.Type = type;
}
}
}
}

View file

@ -1,8 +1,8 @@
namespace Cosmos.HAL
namespace Cosmos.System
{
public class KeyMapping
{
public uint Scancode;
public byte Scancode;
public char Value;
public char Shift;
public char Num;
@ -12,7 +12,7 @@ namespace Cosmos.HAL
public ConsoleKeyEx Key;
public ConsoleKeyEx NumLockKey;
public KeyMapping(uint aScanCode, char norm, char shift, char num, char caps, char shiftcaps, char shiftnum, ConsoleKeyEx aKey)
public KeyMapping(byte aScanCode, char norm, char shift, char num, char caps, char shiftcaps, char shiftnum, ConsoleKeyEx aKey)
{
Scancode = aScanCode;
Value = norm;
@ -25,30 +25,30 @@ namespace Cosmos.HAL
NumLockKey = aKey;
}
public KeyMapping(uint aScanCode, char norm, char shift, char num, char caps, char shiftcaps, char shiftnum, ConsoleKeyEx aKey, ConsoleKeyEx numKey)
public KeyMapping(byte aScanCode, char norm, char shift, char num, char caps, char shiftcaps, char shiftnum, ConsoleKeyEx aKey, ConsoleKeyEx numKey)
: this(aScanCode, norm, shift, num, caps, shiftcaps, shiftnum, aKey)
{
NumLockKey = numKey;
}
public KeyMapping(uint aScanCode, char num, ConsoleKeyEx aKey, ConsoleKeyEx numKey)
public KeyMapping(byte aScanCode, char num, ConsoleKeyEx aKey, ConsoleKeyEx numKey)
: this(aScanCode, '\0', '\0', num, '\0', '\0', '\0', aKey, numKey)
{
}
public KeyMapping(uint aScanCode, int norm, int shift, int num, int caps, int shiftcaps, int shiftnum, ConsoleKeyEx aKey)
public KeyMapping(byte aScanCode, int norm, int shift, int num, int caps, int shiftcaps, int shiftnum, ConsoleKeyEx aKey)
: this(aScanCode, (char)norm, (char)shift, (char)num, (char)caps, (char)shiftcaps, (char)shiftnum, aKey)
{
}
public KeyMapping(uint aScanCode, char n, ConsoleKeyEx aKey)
public KeyMapping(byte aScanCode, char n, ConsoleKeyEx aKey)
: this(aScanCode, n, n, n, n, n, n, aKey)
{
}
public KeyMapping(uint aScanCode, ConsoleKeyEx aKey)
public KeyMapping(byte aScanCode, ConsoleKeyEx aKey)
: this(aScanCode, '\0', '\0', '\0', '\0', '\0', '\0', aKey)
{
}
}
}
}

View file

@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmos.Debug.Kernel;
using Cosmos.HAL;
using Cosmos.System.ScanMaps;
namespace Cosmos.System
{
public class Keyboard
{
public bool NumLock
{
get;
set;
}
public bool CapsLock
{
get;
set;
}
public bool ScrollLock
{
get;
set;
}
public bool ControlPressed
{
get;
set;
}
public bool ShiftPressed
{
get;
set;
}
public bool AltPressed
{
get;
set;
}
protected KeyboardBase _keyboard;
protected ScanMapBase _scanMap;
protected Queue<KeyEvent> mQueuedKeys;
public Keyboard(KeyboardBase Keyboard, ScanMapBase ScanMap)
{
_keyboard = Keyboard;
_keyboard.OnKeyPressed += new KeyboardBase.KeyPressedEventHandler(HandleScanCode);
if(ScanMap == null)
{
ScanMap = new US_Standard();
}
_scanMap = ScanMap;
mQueuedKeys = new Queue<KeyEvent>();
}
protected void Enqueue(KeyEvent keyEvent)
{
mQueuedKeys.Enqueue(keyEvent);
}
/// <summary>
/// Allow faking scancodes. Used for test kernels
/// </summary>
internal void HandleFakeScanCode(byte aScancode, bool aReleased)
{
HandleScanCode(aScancode, aReleased);
}
protected void HandleScanCode(byte aScanCode, bool aReleased)
{
byte key = aScanCode;
if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.CapsLock) && !aReleased)
{
// caps lock
CapsLock = !CapsLock;
_keyboard.UpdateLeds();
}
else if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.NumLock) && !aReleased)
{
// num lock
NumLock = !NumLock;
_keyboard.UpdateLeds();
}
else if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.ScrollLock) && !aReleased)
{
// scroll lock
ScrollLock = !ScrollLock;
_keyboard.UpdateLeds();
}
else if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.LCtrl) || _scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.RCtrl))
{
ControlPressed = !aReleased;
}
else if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.LShift) || _scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.RShift))
{
ShiftPressed = !aReleased;
}
else if (_scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.LAlt) || _scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.RAlt))
{
AltPressed = !aReleased;
}
else
{
if (ControlPressed && AltPressed && _scanMap.ScanCodeMatchesKey(key, ConsoleKeyEx.Delete))
{
Global.Console.WriteLine("Detected Ctrl-Alt-Delete! Rebooting System...");
Power.Reboot();
}
if (!aReleased)
{
KeyEvent keyInfo;
if (GetKey(key, out keyInfo))
{
Enqueue(keyInfo);
}
}
}
}
public bool GetKey(byte aScancode, out KeyEvent keyInfo)
{
if (_scanMap == null)
{
Debugger.DoSend("No KeyLayout");
}
keyInfo = _scanMap.ConvertScanCode(aScancode, ControlPressed, ShiftPressed, AltPressed, NumLock, CapsLock, ScrollLock);
return keyInfo != null;
}
public bool TryReadKey(out KeyEvent oKey)
{
if (mQueuedKeys.Count > 0)
{
oKey = mQueuedKeys.Dequeue();
return true;
}
oKey = default(KeyEvent);
return false;
}
public KeyEvent ReadKey()
{
while (mQueuedKeys.Count == 0)
{
_keyboard.WaitForKey();
}
return mQueuedKeys.Dequeue();
}
public ScanMapBase GetKeyLayout()
{
return _scanMap;
}
public void SetKeyLayout(ScanMapBase ScanMap)
{
_scanMap = ScanMap;
}
}
}

View file

@ -3,9 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmos.Debug.Kernel;
namespace Cosmos.HAL
using Cosmos.Debug.Kernel;
using Cosmos.HAL;
namespace Cosmos.System
{
public abstract class ScanMapBase
{
@ -76,5 +78,18 @@ namespace Cosmos.HAL
}
return found ? keyev : null;
}
public bool ScanCodeMatchesKey(byte ScanCode, ConsoleKeyEx Key)
{
for (int i = 0; i < _keys.Count; i++)
{
if (_keys[i].Scancode == ScanCode && _keys[i].Key == Key)
{
return true;
}
}
return false;
}
}
}

View file

@ -6,7 +6,7 @@ using Cosmos.HAL;
namespace Cosmos.System.ScanMaps
{
public class FR_Standard : ScanMap
public class FR_Standard : ScanMapBase
{
protected override void InitKeys()
{

View file

@ -6,7 +6,7 @@ using Cosmos.HAL;
namespace Cosmos.System.ScanMaps
{
public class US_Standard : ScanMap
public class US_Standard : ScanMapBase
{
public US_Standard()
{

View file

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmos.HAL;
namespace Cosmos.System.ScanMaps
{
public abstract class ScanMap : ScanMapBase
{
}
}

View file

@ -8,11 +8,11 @@ namespace Cosmos.System
internal static void KeyboardAddFakeScanCode(byte aScanCode, bool aReleased)
{
Debugger.DoSend("Before HandleFakeScanCode");
if (HAL.Global.Keyboard == null)
if (Global.Keyboard == null)
{
Debugger.DoSend("No Keyboard set!");
}
HAL.Global.Keyboard.HandleFakeScanCode(aScanCode, aReleased);
Global.Keyboard.HandleFakeScanCode(aScanCode, aReleased);
Debugger.DoSend("After HandleFakeScanCode");
}
}