/* * Copyright (c) 2020, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include namespace Kernel { #define I8042_BUFFER 0x60 #define I8042_STATUS 0x64 #define I8042_ACK 0xFA #define I8042_RESEND 0xFE #define I8042_BUFFER_FULL 0x01 #define I8042_WHICH_BUFFER 0x20 #define I8042_KEYBOARD_BUFFER 0x00 #define I8042_MOUSE_BUFFER 0x20 class I8042Controller; class I8042Device { public: virtual ~I8042Device() = default; virtual void irq_handle_byte_read(u8 byte) = 0; protected: explicit I8042Device(const I8042Controller& ps2_controller) : m_i8042_controller(ps2_controller) { } NonnullRefPtr m_i8042_controller; }; class PS2KeyboardDevice; class PS2MouseDevice; class I8042Controller : public RefCounted { friend class PS2KeyboardDevice; friend class PS2MouseDevice; public: static NonnullRefPtr initialize(); void detect_devices(); bool reset_device(HIDDevice::Type device) { ScopedSpinLock lock(m_lock); return do_reset_device(device); } u8 send_command(HIDDevice::Type device, u8 command) { ScopedSpinLock lock(m_lock); return do_send_command(device, command); } u8 send_command(HIDDevice::Type device, u8 command, u8 data) { ScopedSpinLock lock(m_lock); return do_send_command(device, command, data); } u8 read_from_device(HIDDevice::Type device) { ScopedSpinLock lock(m_lock); return do_read_from_device(device); } void wait_then_write(u8 port, u8 data) { ScopedSpinLock lock(m_lock); do_wait_then_write(port, data); } u8 wait_then_read(u8 port) { ScopedSpinLock lock(m_lock); return do_wait_then_read(port); } void prepare_for_output(); void prepare_for_input(HIDDevice::Type); void irq_process_input_buffer(HIDDevice::Type); RefPtr mouse() const; RefPtr keyboard() const; private: I8042Controller(); void do_drain(); bool do_reset_device(HIDDevice::Type); u8 do_send_command(HIDDevice::Type type, u8 data); u8 do_send_command(HIDDevice::Type device, u8 command, u8 data); u8 do_write_to_device(HIDDevice::Type device, u8 data); u8 do_read_from_device(HIDDevice::Type device); void do_wait_then_write(u8 port, u8 data); u8 do_wait_then_read(u8 port); SpinLock m_lock; bool m_first_port_available { false }; bool m_second_port_available { false }; bool m_is_dual_channel { false }; RefPtr m_mouse_device; RefPtr m_keyboard_device; }; }