1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Core; 12 13 namespace Antmicro.Renode.Peripherals.Input 14 { 15 public class PS2Keyboard : IPS2Peripheral, IKeyboard 16 { PS2Keyboard()17 public PS2Keyboard() 18 { 19 data = new Queue<byte>(); 20 Reset(); 21 data.Enqueue((byte)Command.SelfTestPassed); 22 } 23 Read()24 public byte Read() 25 { 26 if(data.Count > 0) 27 { 28 var result = data.Dequeue(); 29 NotifyParent(); 30 return result; 31 } 32 this.Log(LogLevel.Warning, "Attempted to read while no data in buffer. Returning 0."); 33 return 0; 34 } 35 Write(byte value)36 public void Write(byte value) 37 { 38 switch((Command)value) 39 { 40 case Command.Reset: 41 Reset(); 42 lock(data) 43 { 44 SendAck(); 45 data.Enqueue((byte)Command.SelfTestPassed); 46 } 47 break; 48 case Command.ReadId: 49 lock(data) 50 { 51 SendAck(); 52 data.Enqueue((byte) (deviceId >> 8)); 53 data.Enqueue((byte) (deviceId & 0xff)); 54 } 55 break; 56 default: 57 this.Log(LogLevel.Warning, "Unhandled PS2 keyboard command: {0}", value); 58 break; 59 } 60 } 61 Press(KeyScanCode scanCode)62 public void Press(KeyScanCode scanCode) 63 { 64 var key = PS2ScanCodeTranslator.Instance.GetCode(scanCode); 65 data.Enqueue((byte)(key & 0x7f)); 66 NotifyParent(); 67 } 68 Release(KeyScanCode scanCode)69 public void Release(KeyScanCode scanCode) 70 { 71 var key = PS2ScanCodeTranslator.Instance.GetCode(scanCode); 72 data.Enqueue((byte)Command.Release); 73 data.Enqueue((byte)(key & 0x7f)); 74 NotifyParent(); 75 } 76 Reset()77 public void Reset() 78 { 79 data.Clear(); 80 } 81 82 public IPS2Controller Controller { get; set; } 83 SendAck()84 private void SendAck() 85 { 86 data.Enqueue((byte)Command.Acknowledge); 87 NotifyParent(); 88 } 89 NotifyParent()90 private void NotifyParent() 91 { 92 if(Controller != null) 93 { 94 if(data.Count > 0) 95 { 96 Controller.Notify(); 97 } 98 } 99 else 100 { 101 this.Log(LogLevel.Noisy, "PS2 device not connected to any controller issued an update."); 102 } 103 } 104 105 private readonly Queue<byte> data; 106 private const ushort deviceId = 0xABBA; 107 108 private enum Command 109 { 110 Reset = 0xFF, 111 Acknowledge = 0xFA, 112 ReadId = 0xF2, 113 SetResetLeds = 0xED, 114 Release = 0xF0, 115 SelfTestPassed = 0xAA, 116 } 117 } 118 } 119