Page 1 of 1

Keyboard Issues

Posted: Sun Jul 29, 2007 8:17 pm
by jzgriffin
Hey,

My OS freezes whenever I do something similar to the following:

Code: Select all

// code
char buffer[1024];
keyboardRead(buffer);
 
// keyboard.h
#ifndef __K_KEYBOARD_H__
#define __K_KEYBOARD_H__
 
#include <kernel.lib/assembly.h>
 
#define KEY_SHIFT 1
 
extern unsigned char keyChr;
 
extern void keyboardRead(char *buffer);
extern void keyboardClearKey();
extern void keyboardHandler(struct TRegisters *registers);
extern void keyboardInit();
 
#endif // __K_KEYBOARD_H__
 
// keyboard.c
#include <kernel.lib/hardware.h>
#include <kernel.lib/memory.h>
#include <kernel.lib/vga.h>
#include <kernel.sys/irq.h>
#include <kernel.sys/keyboard.h>
#include <kernel.sys/timer.h>
 
int keyboardScan = 0;
char *keyBuf;
unsigned short keyboardStatus = 0;
unsigned char keyboard[1][2][128] = {
  {
    {
         0,   27,  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',  '0',  '-',
       '=', '\b', '\t',  'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',  'o',  'p',
       '[',  ']', '\n',    0,  'a',  's',  'd',  'f',  'g',  'h',  'j',  'k',  'l',
       ';', '\'',  '`',    0, '\\',  'z',  'x',  'c',  'v',  'b',  'n',  'm',  ',',
       '.',  '/',    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,   27,  '!',  '@',  '#',  '$',  '%',  '^',  '&',  '*',  '(',  ')',  '_',
       '+', '\b', '\t',  'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',  'O',  'P',
       '{',  '}', '\n',    0,  'A',  'S',  'D',  'F',  'G',  'H',  'J',  'K',  'L',
       ':',  '"',  '~',    0,  '|',  'Z',  'X',  'C',  'V',  'B',  'N',  'M',  '<',
       '>',  '?',    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
    }
  }
}, keyChr = '\0';
 
/**
 * keyboardRead - Starts reading to a user-specified buffer
 *     buffer   - Pointer to the buffer
 */
void keyboardRead(char *buffer) {
  keyboardScan = 1;
  keyBuf = buffer;
 
  while (keyboardScan == 1) {
  }
}
 
/**
 * keyboardHandler - Handles keypresses
 *     registers   - Registers at the time of the event
 */
void keyboardHandler(struct TRegisters *registers) {
  unsigned char scanCode;
 
  // Get rid of those nasty unused parameter warnings
  if (registers->intNumber == 1) { }
 
  // Read the byte from port 0x60
  scanCode = readB(0x60);
 
  if (scanCode == 42 || scanCode == 54) {
    keyboardStatus |= (1 << KEY_SHIFT);
  }
  if (scanCode == 42 + 128 || scanCode == 54 + 128) {
    keyboardStatus &= ~(1 << KEY_SHIFT);
  }
 
  if (keyboardStatus & (1 << KEY_SHIFT)) {
    keyChr = keyboard[0][1][scanCode];
    printChr(keyChr);
    if (keyboardScan == 1) {
      if (keyChr == '\n') {
        keyboardScan = 0;
      } else {
        *keyBuf++ = keyChr;
      }
    }
  } else {
    // Make sure that this isn't a released key!
    if (scanCode < 128) {
      keyChr = keyboard[0][0][scanCode];
      printChr(keyChr);
      if (keyboardScan == 1) {
        if (keyChr == '\n') {
          keyboardScan = 0;
        } else {
          *keyBuf++ = keyChr;
        }
      }
    }
  }
 
  writeB(0x20, 0x20);
}
 
/**
 * keyboardInit - Initializes the keyboard
 */
void keyboardInit() {
  irqInstall(1, keyboardHandler);
}
What I'm trying to do is implement something similar to fgets, gets, etc. Please help, I've been working on this for several hours, and have tried lots of methods, but can't get it working. :(

Posted: Mon Jul 30, 2007 1:28 am
by JamesM
Please help, I've been working on this for several hours
Bugs can take more than several hours looking at it to work out. Come back if you're still stuck after about 4 days (Thats about the cutoff period I set myself before I ask for help).

JamesM

Posted: Mon Jul 30, 2007 1:43 am
by AJ

Code: Select all

while (keyboardScan == 1) { 
  } 
That looks a little suspicious to me...

If that's not the problem, are you using Bochs or similar? Where exactly is EIP when the freeze occurs (always the same value, always the same function etc...)?

Cheers,
Adam

Posted: Mon Jul 30, 2007 1:54 am
by pcmattman
Why don't I see the volatile keyword anywhere in this code?

Posted: Mon Jul 30, 2007 2:55 am
by JamesM
@OP: In case you didn't understand what pcmattman said, GCC will cache any variable it thinks will remain static within a specified scope, for performance reasons. This causes problems when manipulating shared data across threads/processes. Your spin variable (keyboardScan) should be declared 'volatile', to tell gcc NEVER to cache it's value.

JamesM

Posted: Mon Jul 30, 2007 11:55 am
by jzgriffin
geist helped me with this on #osdev a little while after I posted this topic. I didn't know about volatiles before. But the problem was that I had my sti() in kernel() (different file) *after* the call to getStr/keyboardRead. It works perfectly now, and I've practically rewritten the driver.