I8042Controller.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/RefCounted.h>
  8. #include <Kernel/Devices/HID/KeyboardDevice.h>
  9. #include <Kernel/Devices/HID/MouseDevice.h>
  10. #include <Kernel/Locking/Spinlock.h>
  11. namespace Kernel {
  12. #define I8042_BUFFER 0x60
  13. #define I8042_STATUS 0x64
  14. #define I8042_ACK 0xFA
  15. #define I8042_RESEND 0xFE
  16. #define I8042_BUFFER_FULL 0x01
  17. #define I8042_WHICH_BUFFER 0x20
  18. #define I8042_KEYBOARD_BUFFER 0x00
  19. #define I8042_MOUSE_BUFFER 0x20
  20. class I8042Controller;
  21. class I8042Device {
  22. public:
  23. virtual ~I8042Device() = default;
  24. virtual void irq_handle_byte_read(u8 byte) = 0;
  25. protected:
  26. explicit I8042Device(const I8042Controller& ps2_controller)
  27. : m_i8042_controller(ps2_controller)
  28. {
  29. }
  30. NonnullRefPtr<I8042Controller> m_i8042_controller;
  31. };
  32. class PS2KeyboardDevice;
  33. class PS2MouseDevice;
  34. class I8042Controller : public RefCounted<I8042Controller> {
  35. friend class PS2KeyboardDevice;
  36. friend class PS2MouseDevice;
  37. public:
  38. static NonnullRefPtr<I8042Controller> initialize();
  39. void detect_devices();
  40. bool reset_device(HIDDevice::Type device)
  41. {
  42. SpinlockLocker lock(m_lock);
  43. return do_reset_device(device);
  44. }
  45. u8 send_command(HIDDevice::Type device, u8 command)
  46. {
  47. SpinlockLocker lock(m_lock);
  48. return do_send_command(device, command);
  49. }
  50. u8 send_command(HIDDevice::Type device, u8 command, u8 data)
  51. {
  52. SpinlockLocker lock(m_lock);
  53. return do_send_command(device, command, data);
  54. }
  55. u8 read_from_device(HIDDevice::Type device)
  56. {
  57. SpinlockLocker lock(m_lock);
  58. return do_read_from_device(device);
  59. }
  60. void wait_then_write(u8 port, u8 data)
  61. {
  62. SpinlockLocker lock(m_lock);
  63. do_wait_then_write(port, data);
  64. }
  65. u8 wait_then_read(u8 port)
  66. {
  67. SpinlockLocker lock(m_lock);
  68. return do_wait_then_read(port);
  69. }
  70. void prepare_for_output();
  71. void prepare_for_input(HIDDevice::Type);
  72. bool irq_process_input_buffer(HIDDevice::Type);
  73. RefPtr<MouseDevice> mouse() const;
  74. RefPtr<KeyboardDevice> keyboard() const;
  75. private:
  76. I8042Controller();
  77. void do_drain();
  78. bool do_reset_device(HIDDevice::Type);
  79. u8 do_send_command(HIDDevice::Type type, u8 data);
  80. u8 do_send_command(HIDDevice::Type device, u8 command, u8 data);
  81. u8 do_write_to_device(HIDDevice::Type device, u8 data);
  82. u8 do_read_from_device(HIDDevice::Type device);
  83. void do_wait_then_write(u8 port, u8 data);
  84. u8 do_wait_then_read(u8 port);
  85. Spinlock<u8> m_lock;
  86. bool m_first_port_available { false };
  87. bool m_second_port_available { false };
  88. bool m_is_dual_channel { false };
  89. RefPtr<MouseDevice> m_mouse_device;
  90. RefPtr<KeyboardDevice> m_keyboard_device;
  91. };
  92. }