Page 1 of 1

keyboard problem

Posted: Sat Aug 14, 2004 1:28 pm
by kiran
hello

i have a small keyboard problem. When i press shift and type i get capital letters but even after releasing shift i get capital letters. But sometimes this problem doesnt happen and everything works fine. But with caps lock it works perfectly all the time. I took the code from geezer's osd8 kernel. I modified it slightly

heres part of that code


   
static unsigned short kbd_status=0;
static unsigned short saw_break_code=0;


static unsigned convert(byte key)
{
   

   unsigned short temp=0;


   /* check for break key (i.e. a key is released) */
   if(key >= 0x80)
   {
      saw_break_code = 1;
      key &= 0x7F;
   }

   /* the only break codes we're interested in are Shift, Ctrl, Alt */
   if(saw_break_code)
   {
      if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT)
         kbd_status &= ~KBD_META_ALT;
      else if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL)
         kbd_status &= ~KBD_META_CTRL;
      else if((key == RAW1_LEFT_SHIFT) || (key == RAW1_RIGHT_SHIFT))
      {
         kbd_status &= ~KBD_META_SHIFT;
      
      }
      saw_break_code = 0;
      return 0;
   }

   /* it's a make key: check the "meta" keys, as above */
   if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT)
   {
      kbd_status |= KBD_META_ALT;
      return 0;
   }
   if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL)
   {
      kbd_status |= KBD_META_CTRL;
      return 0;
   }
   if(key == RAW1_LEFT_SHIFT || key == RAW1_RIGHT_SHIFT)
   {
      kbd_status |= KBD_META_SHIFT;
      return 0;
   }

   if(key == RAW1_CAPS_LOCK)
   {
      kbd_status ^= KBD_META_CAPS;
      write_kbd(0x60, 0xED);   /* "set LEDs" command */
      temp = 0;
      if(kbd_status & KBD_META_CAPS)
         temp |= 4;
      write_kbd(0x60, temp);   /* bottom 3 bits set LEDs */
      return 0;
   }

   /* ignore invalid scan codes */
   if(key >= sizeof(set1_map) / sizeof(set1_map[0]))
      return 0;

   /* convert raw scancode in key to ASCII in temp */
   if((kbd_status & KBD_META_SHIFT) || (kbd_status & KBD_META_CAPS))
   {
      temp = set1_map[key][1];
      /*Column 1 for shifted characters/*
   
   }
   else
   {
      temp = set1_map[key][0];
      /*Column 0 for shifted characters/*
   }
   

   if(temp == 0)
      return temp;

   return temp;
}


void kbd_handler(void)
{
   byte key, i;

/* get scancode from port 0x60 */
   key = inportb(0x60);

      i = convert(key);
      if(i != 0)
         printc(i);
      
}

kiran

Re:keyboard problem

Posted: Sun Aug 15, 2004 4:19 am
by Brendan
Hi,

Your "kbd_status" has a single flag for both shift keys ("KBD_META_SHIFT"). Think of this sequence:

left shift pressed kbd_status=KBD_META_SHIFT
right shift pressed kbd_status=KBD_META_SHIFT
left shift released kbd_status=0
'A' key pressed

Now when the A key is pressed the right shift is still down, and a capital 'A' should be sent, but as you've only got one flag for both shift keys you'd end up sending a lower case 'a'.

You've got the same problem with your control and alt keys.

Where you've got this code:

Code: Select all

/* convert raw scancode in key to  ASCII in temp */
   if((kbd_status & KBD_META_SHIFT) || (kbd_status & KBD_META_CAPS))
You should have something like:

Code: Select all

/* convert raw scancode in key to  ASCII in temp */
   if((kbd_status & KBD_LEFT_SHIFT) || (kbd_status & KBD_RIGHT_SHIFT))
Also notice how I removed the test for "KBD_META_CAPS" above. This is because you don't handle CAPS LOCK correctly either. For example, imagine the user presses the keys 'a', 'b', '1' and '2':
Normal: Expected = "ab12", Yours = "ab12" (good)
With shift: Expected = "AB!@", Yours = "AB!@" (good)
With CAPS LOCK: Expected = "AB12", Yours = "AB!@"
With CAPS and shift: Expected = "ab!@", Yours = "AB!@"

This means that instead of your table having 2 columns (normal and with shift), you should actually have 4 columns (normal, with shift, with CAPS LOCK, with shift and CAPS LOCK).


Also the keyboard can send data that has nothing to do with any of the keys, including:
0x00 Keyboard error
0xAA Basic assurance test end
0xFA ACKnowledge
0xFE Resend
0xFF Keyboard error

For example, when you send the command to change keyboard LEDs the keyboard should return 0xFA (acknowledge), which your driver will interpret as a break code for key 0x7A. If the user has a manual switch box (to allow several computers to use the same keyboard/mouse/video - I use 3 of them) then you can get 0xAA (BAT), which you'd interpret as break code 0x2A (which is the left shift key).

Then there's escape codes (0xE0 and 0xE1), which precede the make and break for some keys. For example when the "PRNT SCRN" key is pressed it sends 0xE0, 0x2A, 0xE0, 0x37, which your driver would interpret as break code 0x60, make code left shift, break code 0x60, make code keypad '*'.

Of course some of these problems may be acceptable..

Cheers,

Brendan