// // Created by rick on 23-03-20. // #include "keyboard.h" #include #include #include #include #include #include #include const char scancode_map_lowercase[] = { 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0, 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const char scancode_map_uppercase[] = { 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // //char scancodes_ascii[] = { // 0, 0, // '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, // 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0, // 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', // 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, // '*', // 0, ' ', // 0, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10 // 0, 0, // '7', '8', '9', '-', // '4', '5', '6', '+', // '1', '2', '3', // '0', 0, // 0, // sysrq // 0, 0, // weird // 0, 0, // F11 F12 // // weid //}; struct { u8 shift: 1; u8 ctrl: 1; u8 alt: 1; u8 extended: 1; } keyboard_state; void *keyboard_event_buffer = NULL; char *MSG_KEY = "Clicked on key 'x'\n"; char getc() { while (true) { KeyEvent* event = get_next_event(); char retval = 0; if (event == NULL) { goto _getc_end; } if (event->is_release) { goto _getc_end; } if (event->scancode == 0x1C) { retval = '\n'; goto _getc_end; } if (event->ascii_code != 0) { retval = event->ascii_code; goto _getc_end; } _getc_end: free_event(event); if (retval != 0) { return retval; } } } KeyEvent *get_next_event() { KeyEvent *target = malloc(sizeof(KeyEvent)); if (!ring_buffer_get(keyboard_event_buffer, target)) { asm("hlt"); free(target); return NULL; } return target; }; void free_event(KeyEvent *event) { free(event); } //void print_scancode(unsigned char scancode); void handle_modifier_keys(unsigned char scancode, bool is_release) { switch (scancode) { case 42: case 54: keyboard_state.shift = !is_release; break; case 29: keyboard_state.ctrl = !is_release; break; case 56: keyboard_state.alt = !is_release; break; default: // not an modifier key break; } } void publish_key_event(unsigned char scan_code) { bool is_release = false; if (scan_code > 0x80) { is_release = true; scan_code -= 0x80; } handle_modifier_keys(scan_code, is_release); char ascii_char = scancode_map_lowercase[scan_code]; if (keyboard_state.shift) { if (scancode_map_uppercase[scan_code] != 0) { ascii_char = scancode_map_uppercase[scan_code]; } } KeyEvent event = { .scancode = scan_code, .ascii_code = ascii_char, .is_release = !is_release, .shift = keyboard_state.shift, .alt = keyboard_state.alt, .ctrl = keyboard_state.ctrl, }; ring_buffer_put(keyboard_event_buffer, &event); } static void keyboard_callback(registers_t regs) { unsigned char status = port_byte_in(PORT_PS2_STATUS); // check if data available if ((status & 0b00000001) == 0) { return; } unsigned char scancode = port_byte_in(PORT_PS2_DATA); publish_key_event(scancode); // print_scancode(scancode); } void init_keyboard() { register_interrupt_handler(IRQ1, keyboard_callback); keyboard_state.shift = 0; keyboard_state.ctrl = 0; keyboard_state.alt = 0; keyboard_state.extended = 0; keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent)); } //void print_scancode(unsigned char scancode) { // char msg[256]; // char release = 0; // if (scancode > 0x80) { // // release // release = 1; // scancode -= 0x80; // } // char code = scancodes_ascii[scancode]; // if (code == 0) { // // special // } else { // if (release && code > 0x60 && code < 0x7B) { // code -= 0x20; // to lowercase // } // // strcpy(msg, MSG_KEY); // msg[strlen(msg) - 3] = code; // kprint(msg); // } //}