/* Calcite, src/kernel/ps2.c * Copyright 2025-2026 Benji Dial * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "input.h" #include "ps2.h" #include #include //defined in ps2.asm //returns -1 if no byte available int read_ps2_byte(); static uint8_t keyboard_packet[7]; static int keyboard_packet_length = 0; void on_keyboard_irq() { int byte = read_ps2_byte(); if (byte == -1) return; if (keyboard_packet_length == 0 && byte != 0xe0 && byte != 0xe1 && byte != 0xf0) { add_keyboard_packet(KEY_FLAG_MAKE | byte); return; } if (keyboard_packet_length == 1 && keyboard_packet[0] == 0xe0 && byte != 0xf0 && byte != 0x12) { add_keyboard_packet(KEY_FLAG_MAKE | 0x80 | byte); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 1 && keyboard_packet[0] == 0xf0) { add_keyboard_packet(byte); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 2 && keyboard_packet[0] == 0xe0 && keyboard_packet[1] == 0xf0 && byte != 0x7c) { add_keyboard_packet(0x80 | byte); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 3 && keyboard_packet[0] == 0xe0 && keyboard_packet[1] == 0x12 && keyboard_packet[2] == 0xe0 && byte == 0x7c) { add_keyboard_packet(KEY_FLAG_MAKE | KEY_PRINT_SCREEN); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 5 && keyboard_packet[0] == 0xe0 && keyboard_packet[1] == 0xf0 && keyboard_packet[2] == 0x7c && keyboard_packet[3] == 0xe0 && keyboard_packet[4] == 0xf0 && byte == 0x12) { add_keyboard_packet(KEY_PRINT_SCREEN); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 7 && keyboard_packet[0] == 0xe1 && keyboard_packet[1] == 0x14 && keyboard_packet[2] == 0x77 && keyboard_packet[3] == 0xe1 && keyboard_packet[4] == 0xf0 && keyboard_packet[5] == 0x14 && keyboard_packet[6] == 0xf0 && byte == 0x77) { add_keyboard_packet(KEY_FLAG_MAKE | KEY_PAUSE_BREAK); add_keyboard_packet(KEY_PAUSE_BREAK); keyboard_packet_length = 0; return; } if (keyboard_packet_length == 7) { keyboard_packet_length = 0; return; } keyboard_packet[keyboard_packet_length++] = byte; } static uint8_t mouse_packet[3]; static int mouse_packet_length = 0; void on_mouse_irq() { int byte = read_ps2_byte(); if (byte == -1) return; mouse_packet[mouse_packet_length] = byte; if (mouse_packet_length < 2) { ++mouse_packet_length; return; } mouse_packet_length = 0; int x_change = mouse_packet[1]; if (mouse_packet[0] & 0x10) x_change -= 256; int y_change = mouse_packet[2]; if (mouse_packet[0] & 0x20) y_change -= 256; add_mouse_movement(x_change, y_change); }