119 lines
3.0 KiB
C
119 lines
3.0 KiB
C
|
/* Copyright (C) 2005 Thomas Petazzoni
|
||
|
|
||
|
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 2
|
||
|
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, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||
|
USA.
|
||
|
*/
|
||
|
|
||
|
#include <sos/types.h>
|
||
|
#include <sos/errno.h>
|
||
|
#include <sos/assert.h>
|
||
|
#include <hwcore/irq.h>
|
||
|
#include <hwcore/ioports.h>
|
||
|
|
||
|
#include "tty.h"
|
||
|
|
||
|
/*
|
||
|
* Keyboard ports and commands.
|
||
|
*
|
||
|
* @see Ralf Brown's interrupt (and port) list
|
||
|
* http://www-2.cs.cmu.edu/~ralf/files.html
|
||
|
*/
|
||
|
|
||
|
#define KBD_DATA_PORT 0x60
|
||
|
|
||
|
#define KBD_BREAKCODE_LIMIT 0x80
|
||
|
#define KBD_EXTENDED_SCANCODE 0xE0
|
||
|
|
||
|
#define KBD_IS_MAKECODE(c) ((c) < KBD_BREAKCODE_LIMIT)
|
||
|
#define KBD_IS_BREAKCODE(c) ((c) >= KBD_BREAKCODE_LIMIT)
|
||
|
#define KBD_BREAKCODE_2_MAKECODE(c) ((c) ^ KBD_BREAKCODE_LIMIT)
|
||
|
|
||
|
#define KBD_LEFTSHIFT_SCANCODE 0x2a
|
||
|
#define KBD_RIGHTSHIFT_SCANCODE 0x36
|
||
|
|
||
|
typedef sos_ui8_t scancode_t;
|
||
|
|
||
|
extern const char *kbd_regular_translate_table [];
|
||
|
extern const char *kbd_shift_translate_table [];
|
||
|
|
||
|
static const char **kbd_current_translate_table = kbd_regular_translate_table;
|
||
|
static int is_ext = FALSE;
|
||
|
|
||
|
static struct tty_device *tty;
|
||
|
|
||
|
static void kbd_irq_handler (int irq_level)
|
||
|
{
|
||
|
scancode_t scancode;
|
||
|
const char *key = NULL;
|
||
|
|
||
|
scancode = inb (KBD_DATA_PORT);
|
||
|
|
||
|
/* Mark that next interrupt wil give an extended scancode */
|
||
|
if (scancode == KBD_EXTENDED_SCANCODE)
|
||
|
{
|
||
|
is_ext = TRUE;
|
||
|
}
|
||
|
|
||
|
/* Handle extended scancode */
|
||
|
else if (is_ext)
|
||
|
{
|
||
|
is_ext = FALSE;
|
||
|
}
|
||
|
|
||
|
/* Normal scancode */
|
||
|
else
|
||
|
{
|
||
|
/* Keypressed */
|
||
|
if (KBD_IS_MAKECODE(scancode))
|
||
|
{
|
||
|
/* If shift, change translation table */
|
||
|
if ((scancode == KBD_LEFTSHIFT_SCANCODE) ||
|
||
|
(scancode == KBD_RIGHTSHIFT_SCANCODE))
|
||
|
kbd_current_translate_table = kbd_shift_translate_table;
|
||
|
|
||
|
/* If normal key, compute the result using the translation
|
||
|
tables and the booleans */
|
||
|
else if (kbd_current_translate_table[scancode])
|
||
|
{
|
||
|
key = kbd_current_translate_table[scancode];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Key released */
|
||
|
else
|
||
|
{
|
||
|
scancode_t makecode = KBD_BREAKCODE_2_MAKECODE(scancode);
|
||
|
|
||
|
if ((makecode == KBD_LEFTSHIFT_SCANCODE) ||
|
||
|
(makecode == KBD_RIGHTSHIFT_SCANCODE))
|
||
|
kbd_current_translate_table = kbd_regular_translate_table;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (key)
|
||
|
tty_add_chars (tty, key);
|
||
|
}
|
||
|
|
||
|
|
||
|
sos_ret_t sos_kbd_subsystem_setup(struct tty_device *t)
|
||
|
{
|
||
|
tty = t;
|
||
|
|
||
|
sos_irq_set_routine (SOS_IRQ_KEYBOARD, kbd_irq_handler);
|
||
|
|
||
|
return SOS_OK;
|
||
|
}
|
||
|
|