149 lines
3.1 KiB
C
149 lines
3.1 KiB
C
|
|
#include <types.h>
|
||
|
|
#include <port_io.h>
|
||
|
|
#include <new_tty.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
#include <drivers/irq.h>
|
||
|
|
|
||
|
|
#include <drivers/keyboard.h>
|
||
|
|
|
||
|
|
/*
|
||
|
|
PS/2 Controller IO Ports
|
||
|
|
|
||
|
|
The PS/2 Controller itself uses 2 IO ports (IO ports 0x60 and 0x64). Like many IO ports, reads and writes may access different internal registers.
|
||
|
|
|
||
|
|
Historical note: The PC-XT PPI had used port 0x61 to reset the keyboard interrupt request signal (among other unrelated functions). Port 0x61 has no keyboard related functions on AT and PS/2 compatibles.
|
||
|
|
IO Port Access Type Purpose
|
||
|
|
0x60 Read/Write Data Port
|
||
|
|
0x64 Read Status Register
|
||
|
|
0x64 Write Command Register
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define PS2_DATA_PORT 0x60
|
||
|
|
#define PS2_STATUS_PORT 0x64
|
||
|
|
|
||
|
|
#define KEYBOARD_IRQ 1
|
||
|
|
|
||
|
|
static const char scancode_map[128] = {
|
||
|
|
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=','\b', /* Backspace */
|
||
|
|
'\t', /* Tab */
|
||
|
|
'q','w','e','r','t','y','u','i','o','p','[',']','\n', /* Enter */
|
||
|
|
0, /* Control */
|
||
|
|
'a','s','d','f','g','h','j','k','l',';','\'','`',
|
||
|
|
0, /* Left shift */
|
||
|
|
'\\','z','x','c','v','b','n','m',',','.','/',
|
||
|
|
0, /* Right shift */
|
||
|
|
'*',
|
||
|
|
0, /* Alt */
|
||
|
|
' ', /* Spacebar */
|
||
|
|
0, /* Caps lock */
|
||
|
|
/* The rest are function and control keys */
|
||
|
|
};
|
||
|
|
|
||
|
|
volatile uint32_t mods = 0;
|
||
|
|
volatile bool keyboard_initialied = false;
|
||
|
|
volatile bool extended = false;
|
||
|
|
|
||
|
|
int init_keyboard(void)
|
||
|
|
{
|
||
|
|
#ifdef _DEBUG
|
||
|
|
printf("Initializing the keyboard...\n");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
keyboard_initialied = true;
|
||
|
|
|
||
|
|
set_irq_handler(1, (irq_func_t) keyboard_handler);
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
printf("Keyboard initialized\n");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
registers_t* keyboard_handler(registers_t* regs)
|
||
|
|
{
|
||
|
|
if (!(inb(PS2_STATUS_PORT) & 1))
|
||
|
|
{
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint8_t scancode = inb(PS2_DATA_PORT);
|
||
|
|
|
||
|
|
if (scancode & 0x80)
|
||
|
|
{
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Handle shift press/release */
|
||
|
|
if (scancode == 0x2A || scancode == 0x36)
|
||
|
|
{
|
||
|
|
mods |= MODIFIER_SHIFT;
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
else if (scancode == 0xAA || scancode == 0xB6)
|
||
|
|
{
|
||
|
|
mods &= MODIFIER_SHIFT_DESTROY;
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
else if (scancode == 0x3A)
|
||
|
|
{
|
||
|
|
TOGGLE_BIT(mods, 0); /* TOGGLE_BIT defined in types.h, should move elsewhere. */
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
/*else if (scancode == 0xE0)
|
||
|
|
{
|
||
|
|
extended = true;
|
||
|
|
return;
|
||
|
|
}*/
|
||
|
|
/* XXX: NOTE: we don't do extended codes yet. :NOTE :XXX */
|
||
|
|
/*if (extended)
|
||
|
|
{*/
|
||
|
|
/*switch (scancode)
|
||
|
|
{
|
||
|
|
case 0x48:
|
||
|
|
c = KEY_ARROW_UP;
|
||
|
|
break;
|
||
|
|
case 0x50:
|
||
|
|
c = KEY_ARROW_DOWN;
|
||
|
|
break;
|
||
|
|
case 0x4B:
|
||
|
|
c = KEY_ARROW_LEFT;
|
||
|
|
break;
|
||
|
|
case 0x4D:
|
||
|
|
c = KEY_ARROW_RIGHT;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
c = KEY_NONE;
|
||
|
|
break;
|
||
|
|
}*/
|
||
|
|
|
||
|
|
|
||
|
|
/*tty_receive_char(c, mod);
|
||
|
|
|
||
|
|
extended = false;
|
||
|
|
|
||
|
|
return;
|
||
|
|
}*/
|
||
|
|
|
||
|
|
bool release = scancode & 0x80;
|
||
|
|
scancode &= 0x7F;
|
||
|
|
|
||
|
|
if (release)
|
||
|
|
{
|
||
|
|
return regs;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint16_t c = (uint16_t) scancode_map[scancode];
|
||
|
|
|
||
|
|
if (c)
|
||
|
|
{
|
||
|
|
//tty_receive_char(c, mods);
|
||
|
|
char ch = tty_translate_char(c, mods);
|
||
|
|
tty_input_char(tty_get_active(), ch);
|
||
|
|
}
|
||
|
|
|
||
|
|
return regs;
|
||
|
|
}
|