/* keyboard.c - keyboard functions */ #include #include #include unsigned short keyflags = 0; unsigned short key_extended_buffer; unsigned char keybuffer[256]; unsigned char keybuffer_pointer = 0, keybuffer_count = 0; unsigned char keydata[128] = { 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xDF, '\'', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0xFC, '+', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '^', 0, '#', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0B, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char keydata_shift[128] = { 0, 0, '!', '"', 0xA7, '$', '%', '&', '/', '(', ')', '=', '?', '`', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0xDC, '*', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, 0xB0, 0, '\'', 'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0B, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char keydata_extended[128] = { 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, '\n', 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, 0, 0, 0, 0, 0, 0, 0, 0x0B, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char keydata_altgr[128] = { 0, 0, 0, 0xB2, 0xB3, 0, 0, 0, '{', '[', ']', '}', '\\', 0, '\b', '\t', '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', '\n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xB5, 0, 0, 0, 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0B, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; unsigned char keydata_numlock[13] = { '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ',' }; void update_leds() { register unsigned char al asm("%al"); do { asm ( "in $0x64,%al\n" "and $0b00000010,%al\n" ); } while (al); asm ( "mov $0xED,%al\n" "out %al,$0x60\n" ); do { asm ( "in $0x64,%al\n" "and $0b00000010,%al\n" ); } while (al); asm ( "mov %0,%%eax\n" "and $0b11100000,%%al\n" "shr $5,%%al\n" "out %%al,$0x60\n" : : "m" (keyflags) ); } void kb_write_keycode() { unsigned char keycode; unsigned long fullcode; unsigned char ansicode = 0; unsigned char *keytable = keydata; asm ("mov %%al,%0" : "=m" (keycode)); fullcode = (keycode & KEY_CODE); if(keycode==ACKNOWLEDGE_CODE) return; else if(keycode==EXTENDED0_CODE) {keyflags |= FLAG_EXTENDED_KEY; key_extended_buffer = EXTENDED0_CODE;} else if(keycode==EXTENDED1_CODE) {keyflags |= FLAG_EXTENDED_KEY; key_extended_buffer = EXTENDED1_CODE;} else { if(keyflags & FLAG_EXTENDED_KEY) { if(key_extended_buffer==EXTENDED0_CODE) { fullcode = ((keycode & KEY_CODE) | (EXTENDED0_CODE << 8)); keyflags &= ~FLAG_EXTENDED_KEY; } else if(key_extended_buffer==EXTENDED1_CODE) { fullcode = ((keycode & KEY_CODE) | (EXTENDED1_CODE << 8)); key_extended_buffer = fullcode; } else { fullcode = ((keycode & KEY_CODE) | (((unsigned long)key_extended_buffer) << 8)); keyflags &= ~FLAG_EXTENDED_KEY; } } if(keycode & KEY_RELEASE) { switch(fullcode) { case NUMLOCK_CODE: keyflags &= ~FLAG_NUMLOCK_PRESSED; break; case SCROLLLOCK_CODE: keyflags &= ~FLAG_SCROLLLOCK_PRESSED; break; case CAPSLOCK_CODE: keyflags &= ~FLAG_CAPSLOCK_PRESSED; break; case LSHIFT_CODE: keyflags &= ~FLAG_LSHIFT_PRESSED; break; case RSHIFT_CODE: keyflags &= ~FLAG_RSHIFT_PRESSED; break; case LALT_CODE: keyflags &= ~FLAG_LALT_PRESSED; break; case RALT_CODE: keyflags &= ~FLAG_RALT_PRESSED; break; case LCTRL_CODE: keyflags &= ~FLAG_LCTRL_PRESSED; break; case RCTRL_CODE: keyflags &= ~FLAG_RCTRL_PRESSED; break; default: if((keyflags & FLAG_NUMLOCK_ACTIVE) && (0x47 <= (fullcode & ~KEY_RELEASE)) && ((fullcode & ~KEY_RELEASE) <= 0x53)) ansicode = keydata_numlock[(keycode & KEY_CODE) - 0x47]; else { if((fullcode & (EXTENDED0_CODE << 8)) == (EXTENDED0_CODE << 8)) keytable = keydata_extended; else if(keyflags & FLAG_RALT_PRESSED) keytable = keydata_altgr; else if((keyflags & FLAG_LALT_PRESSED)/* && ((keyflags & FLAG_RCTRL_PRESSED) || (keyflags & FLAG_LCTRL_PRESSED))*/) keytable = keydata_altgr; else if(keyflags & (FLAG_LSHIFT_PRESSED | FLAG_RSHIFT_PRESSED | FLAG_CAPSLOCK_ACTIVE)) keytable = keydata_shift; ansicode = keytable[keycode & KEY_CODE]; } } } else { switch(fullcode) { case NUMLOCK_CODE: if(keyflags & FLAG_NUMLOCK_PRESSED) return; else { keyflags |= FLAG_NUMLOCK_PRESSED; if(keyflags & FLAG_NUMLOCK_ACTIVE) keyflags &= ~FLAG_NUMLOCK_ACTIVE; else keyflags |= FLAG_NUMLOCK_ACTIVE; update_leds(); } break; case SCROLLLOCK_CODE: if(keyflags & FLAG_SCROLLLOCK_PRESSED) return; else { keyflags |= FLAG_SCROLLLOCK_PRESSED; if(keyflags & FLAG_SCROLLLOCK_ACTIVE) keyflags &= ~FLAG_SCROLLLOCK_ACTIVE; else keyflags |= FLAG_SCROLLLOCK_ACTIVE; update_leds(); } break; case CAPSLOCK_CODE: if(keyflags & FLAG_CAPSLOCK_PRESSED) return; else { keyflags |= FLAG_CAPSLOCK_PRESSED; if(keyflags & FLAG_CAPSLOCK_ACTIVE) keyflags &= ~FLAG_CAPSLOCK_ACTIVE; else keyflags |= FLAG_CAPSLOCK_ACTIVE; update_leds(); } break; case LSHIFT_CODE: keyflags |= FLAG_LSHIFT_PRESSED; break; case RSHIFT_CODE: keyflags |= FLAG_RSHIFT_PRESSED; break; case LALT_CODE: keyflags |= FLAG_LALT_PRESSED; break; case RALT_CODE: keyflags |= FLAG_RALT_PRESSED; break; case LCTRL_CODE: keyflags |= FLAG_LCTRL_PRESSED; break; case RCTRL_CODE: keyflags |= FLAG_RCTRL_PRESSED; break; default: if((keyflags & FLAG_NUMLOCK_ACTIVE) && (0x47 <= fullcode) && (fullcode <= 0x53)) ansicode = keydata_numlock[keycode - 0x47]; else { if((fullcode & (EXTENDED0_CODE << 8)) == (EXTENDED0_CODE << 8)) keytable = keydata_extended; else if(keyflags & FLAG_RALT_PRESSED) keytable = keydata_altgr; else if(keyflags & (FLAG_LSHIFT_PRESSED | FLAG_RSHIFT_PRESSED | FLAG_CAPSLOCK_ACTIVE)) keytable = keydata_shift; ansicode = keytable[keycode]; } } } } if(keyflags & FLAG_BUFFER_FULL) return; keybuffer[(keybuffer_pointer + keybuffer_count++) & 0xFF] = keycode; keybuffer[(keybuffer_pointer + keybuffer_count++) & 0xFF] = ansicode; if(keybuffer_count==0) keyflags |= FLAG_BUFFER_FULL; } void kb_read_keycode() { unsigned long keycode = 0; unsigned char ansicode = 0; if((keybuffer_count != 0) || (keyflags & FLAG_BUFFER_FULL)) { keycode = keybuffer[keybuffer_pointer++]; ansicode = keybuffer[keybuffer_pointer++]; keybuffer_count-=2; keyflags &= ~FLAG_BUFFER_FULL; if(keycode == EXTENDED0_CODE) { if(keybuffer_count != 0) { keycode <<= 8; keycode |= keybuffer[keybuffer_pointer++]; ansicode = keybuffer[keybuffer_pointer++]; keybuffer_count-=2; } } else if(keycode == EXTENDED1_CODE) { if(keybuffer_count != 0) { keycode <<= 8; keycode |= keybuffer[keybuffer_pointer++]; ansicode = keybuffer[keybuffer_pointer++]; keybuffer_count-=2; if(keybuffer_count != 0) { keycode <<= 8; keycode |= keybuffer[keybuffer_pointer++]; ansicode = keybuffer[keybuffer_pointer++]; keybuffer_count-=2; } } } } asm ("mov %0,%%eax; mov %1,%%dl" : : "m" (keycode), "m" (ansicode)); }