Reboot when Ctrl+Alt+Del is pressed.
[pintos-anon] / src / devices / kbd.c
index ea9835876a53626e11d00d663e92b7501c4ba157..1aa71f5a3062c1888b3d3342d9a2d6675765b4e6 100644 (file)
@@ -3,27 +3,26 @@
 #include <debug.h>
 #include <stdio.h>
 #include <string.h>
-#include "devices/intq.h"
+#include "devices/input.h"
+#include "threads/init.h"
 #include "threads/interrupt.h"
 #include "threads/io.h"
 
 /* Keyboard data register port. */
 #define DATA_REG 0x60
 
-/* Shift state bits. */
-#define LSHIFT  0x01            /* Left Shift. */
-#define RSHIFT  0x02            /* Right Shift. */
-#define LALT    0x04            /* Left Alt. */
-#define RALT    0x08            /* Right Alt. */
-#define LCTRL   0x10            /* Left Ctrl. */
-#define RCTRL   0x20            /* Right Ctrl. */
-#define CAPS    0x40            /* Caps Lock. */
+/* Current state of shift keys.
+   True if depressed, false otherwise. */
+static bool left_shift, right_shift;    /* Left and right Shift keys. */
+static bool left_alt, right_alt;        /* Left and right Alt keys. */
+static bool left_ctrl, right_ctrl;      /* Left and right Ctl keys. */
 
-/* Current shift state. */
-static unsigned shift_state;
+/* Status of Caps Lock.
+   True when on, false when off. */
+static bool caps_lock;
 
-/* Keyboard buffer. */
-static struct intq buffer;
+/* Number of keys pressed. */
+static int64_t key_cnt;
 
 static intr_handler_func keyboard_interrupt;
 
@@ -31,22 +30,14 @@ static intr_handler_func keyboard_interrupt;
 void
 kbd_init (void) 
 {
-  intq_init (&buffer, "keyboard");
-  intr_register (0x21, 0, INTR_OFF, keyboard_interrupt, "8042 Keyboard");
+  intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard");
 }
 
-/* Retrieves a key from the keyboard buffer.
-   If the buffer is empty, waits for a key to be pressed. */
-uint8_t
-kbd_getc (void) 
+/* Prints keyboard statistics. */
+void
+kbd_print_stats (void) 
 {
-  uint8_t key;
-  
-  intq_lock (&buffer);
-  key = intq_getc (&buffer);
-  intq_unlock (&buffer);
-  
-  return key;
+  printf ("Keyboard: %lld keys pressed\n", key_cnt);
 }
 \f
 /* Maps a set of contiguous scancodes into characters. */
@@ -63,14 +54,15 @@ struct keymap
    that we handle elsewhere.  */
 static const struct keymap invariant_keymap[] = 
   {
-    {0x01, "\033"},
+    {0x01, "\033"},             /* Escape. */
     {0x0e, "\b"},
     {0x0f, "\tQWERTYUIOP"},
-    {0x1c, "\n"},
+    {0x1c, "\r"},
     {0x1e, "ASDFGHJKL"},
     {0x2c, "ZXCVBNM"},
     {0x37, "*"},
     {0x39, " "},
+    {0x53, "\177"},             /* Delete. */
     {0, NULL},
   };
 
@@ -104,10 +96,9 @@ static void
 keyboard_interrupt (struct intr_frame *args UNUSED) 
 {
   /* Status of shift keys. */
-  bool shift = (shift_state & (LSHIFT | RSHIFT)) != 0;
-  bool alt = (shift_state & (LALT | RALT)) != 0;
-  bool ctrl = (shift_state & (LCTRL | RCTRL)) != 0;
-  bool caps = (shift_state & CAPS) != 0;
+  bool shift = left_shift || right_shift;
+  bool alt = left_alt || right_alt;
+  bool ctrl = left_ctrl || right_ctrl;
 
   /* Keyboard scancode. */
   unsigned code;
@@ -133,7 +124,7 @@ keyboard_interrupt (struct intr_frame *args UNUSED)
     {
       /* Caps Lock. */
       if (!release)
-        shift_state ^= CAPS; 
+        caps_lock = !caps_lock;
     }
   else if (map_key (invariant_keymap, code, &c)
            || (!shift && map_key (unshifted_keymap, code, &c))
@@ -142,6 +133,10 @@ keyboard_interrupt (struct intr_frame *args UNUSED)
       /* Ordinary character. */
       if (!release) 
         {
+          /* Reboot if Ctrl+Alt+Del pressed. */
+          if (c == 0177 && ctrl && alt)
+            reboot ();
+
           /* Handle Ctrl, Shift.
              Note that Ctrl overrides Shift. */
           if (ctrl && c >= 0x40 && c < 0x60) 
@@ -149,7 +144,7 @@ keyboard_interrupt (struct intr_frame *args UNUSED)
               /* A is 0x41, Ctrl+A is 0x01, etc. */
               c -= 0x40; 
             }
-          else if (shift == caps)
+          else if (shift == caps_lock)
             c = tolower (c);
 
           /* Handle Alt by setting the high bit.
@@ -159,35 +154,41 @@ keyboard_interrupt (struct intr_frame *args UNUSED)
             c += 0x80;
 
           /* Append to keyboard buffer. */
-          if (!intq_full (&buffer))
-            intq_putc (&buffer, c);
+          if (!input_full ())
+            {
+              key_cnt++;
+              input_putc (c);
+            }
         }
     }
   else
     {
-      /* Table of shift keys.
-         Maps a keycode into a shift_state bit. */
-      static const unsigned shift_keys[][2] = 
+      /* Maps a keycode into a shift state variable. */
+      struct shift_key 
+        {
+          unsigned scancode;
+          bool *state_var;
+        };
+
+      /* Table of shift keys. */
+      static const struct shift_key shift_keys[] = 
         {
-          {  0x2a, LSHIFT},
-          {  0x36, RSHIFT},
-          {  0x38, LALT},
-          {0xe038, RALT},
-          {  0x1d, LCTRL},
-          {0xe01d, RCTRL},
-          {0, 0},
+          {  0x2a, &left_shift},
+          {  0x36, &right_shift},
+          {  0x38, &left_alt},
+          {0xe038, &right_alt},
+          {  0x1d, &left_ctrl},
+          {0xe01d, &right_ctrl},
+          {0,      NULL},
         };
   
-      const unsigned (*key)[2];
+      const struct shift_key *key;
 
       /* Scan the table. */
-      for (key = shift_keys; (*key)[0] != 0; key++) 
-        if ((*key)[0] == code)
+      for (key = shift_keys; key->scancode != 0; key++) 
+        if (key->scancode == code)
           {
-            if (release)
-              shift_state &= ~(*key)[1];
-            else
-              shift_state |= (*key)[1];
+            *key->state_var = !release;
             break;
           }
     }