|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2005 Thomas Petazzoni 002 003 This program is free software; you can redistribute it and/or 004 modify it under the terms of the GNU General Public License 005 as published by the Free Software Foundation; either version 2 006 of the License, or (at your option) any later version. 007 008 This program is distributed in the hope that it will be useful, 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 011 GNU General Public License for more details. 012 013 You should have received a copy of the GNU General Public License 014 along with this program; if not, write to the Free Software 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 016 USA. 017 */ 018 019 #include <sos/types.h> 020 #include <sos/errno.h> 021 #include <sos/assert.h> 022 #include <hwcore/irq.h> 023 #include <hwcore/ioports.h> 024 025 #include "tty.h" 026 027 /* 028 * Keyboard ports and commands. 029 * 030 * @see Ralf Brown's interrupt (and port) list 031 * http://www-2.cs.cmu.edu/~ralf/files.html 032 */ 033 034 #define KBD_DATA_PORT 0x60 035 036 #define KBD_BREAKCODE_LIMIT 0x80 037 #define KBD_EXTENDED_SCANCODE 0xE0 038 039 #define KBD_IS_MAKECODE(c) ((c) < KBD_BREAKCODE_LIMIT) 040 #define KBD_IS_BREAKCODE(c) ((c) >= KBD_BREAKCODE_LIMIT) 041 #define KBD_BREAKCODE_2_MAKECODE(c) ((c) ^ KBD_BREAKCODE_LIMIT) 042 043 #define KBD_LEFTSHIFT_SCANCODE 0x2a 044 #define KBD_RIGHTSHIFT_SCANCODE 0x36 045 046 typedef sos_ui8_t scancode_t; 047 048 extern const char *kbd_regular_translate_table []; 049 extern const char *kbd_shift_translate_table []; 050 051 static const char **kbd_current_translate_table = kbd_regular_translate_table; 052 static int is_ext = FALSE; 053 054 static struct tty_device *tty; 055 056 static void kbd_irq_handler (int irq_level) 057 { 058 scancode_t scancode; 059 const char *key = NULL; 060 061 scancode = inb (KBD_DATA_PORT); 062 063 /* Mark that next interrupt wil give an extended scancode */ 064 if (scancode == KBD_EXTENDED_SCANCODE) 065 { 066 is_ext = TRUE; 067 } 068 069 /* Handle extended scancode */ 070 else if (is_ext) 071 { 072 is_ext = FALSE; 073 } 074 075 /* Normal scancode */ 076 else 077 { 078 /* Keypressed */ 079 if (KBD_IS_MAKECODE(scancode)) 080 { 081 /* If shift, change translation table */ 082 if ((scancode == KBD_LEFTSHIFT_SCANCODE) || 083 (scancode == KBD_RIGHTSHIFT_SCANCODE)) 084 kbd_current_translate_table = kbd_shift_translate_table; 085 086 /* If normal key, compute the result using the translation 087 tables and the booleans */ 088 else if (kbd_current_translate_table[scancode]) 089 { 090 key = kbd_current_translate_table[scancode]; 091 } 092 } 093 094 /* Key released */ 095 else 096 { 097 scancode_t makecode = KBD_BREAKCODE_2_MAKECODE(scancode); 098 099 if ((makecode == KBD_LEFTSHIFT_SCANCODE) || 100 (makecode == KBD_RIGHTSHIFT_SCANCODE)) 101 kbd_current_translate_table = kbd_regular_translate_table; 102 } 103 } 104 105 if (key) 106 tty_add_chars (tty, key); 107 } 108 109 110 sos_ret_t sos_kbd_subsystem_setup(struct tty_device *t) 111 { 112 tty = t; 113 114 sos_irq_set_routine (SOS_IRQ_KEYBOARD, kbd_irq_handler); 115 116 return SOS_OK; 117 } 118
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |