Page 1 of 2

Keyboard led problem

Posted: Mon Mar 28, 2005 12:58 pm
by espenfjo
I`ve been trying to write a keyboard led function. I think i got it all right, but dont seem to work, atleast not in qemu/bochs/vmware.
This is the code:

Code: Select all

if(scancode == 69) /* Numlock */
        {
                while(inportb(0x64) & 0x2);
                        outportb(0x60, 0xed);
                        outportb(0x60, 1);
         }


Re:Keyboard led problem

Posted: Mon Mar 28, 2005 2:01 pm
by pini
I would replace your last outportb by :

Code: Select all

outportb(0x60, 2);
If I remember good, NUM is 2, CAPS is 4 and SCROLL is 0.

Re:Keyboard led problem

Posted: Mon Mar 28, 2005 2:14 pm
by espenfjo
Yeah, thats correct, but '1' should, as far as i know, turn all lights off.

Re:Keyboard led problem

Posted: Mon Mar 28, 2005 2:56 pm
by pini
According to my book (PC Bible, 2nd edition 1989 :P) :

bit 0 is Scroll lock
bit 1 is Num lock
bit 2 is Caps lock

The light is on when the corresponding bit is set, so setting '1' will light SCROLL on and turning all lights on is done with '7'.
Num alone is set with '2' and Caps alone with '4'

Re:Keyboard led problem

Posted: Mon Mar 28, 2005 3:02 pm
by espenfjo
Ok, i've tried nearly all the combinations, but no changes what so ever. :\

Re:Keyboard led problem

Posted: Mon Mar 28, 2005 5:54 pm
by B.E
Try reading the state and the oring the bit

I am not quite show on this but don't you have to wait before you send the next byte after you send the set LED command

Which light come on when you press this button

Re:Keyboard led problem

Posted: Tue Mar 29, 2005 12:15 am
by pini
B.E wrote: I am not quite show on this but don't you have to wait before you send the next byte after you send the set LED command
Right, and one could also check he receives an ACK (0xFA) after sending both bytes.

Re:Keyboard led problem

Posted: Tue Mar 29, 2005 1:32 am
by bubach

Re:Keyboard led problem

Posted: Tue Mar 29, 2005 8:53 am
by Poseidon

Code: Select all

#define scrollock   (unsigned char) 0x01
#define numlock    (unsigned char) 0x02
#define capslock   (unsigned char) 0x04

void kbd_updateleds(unsigned char led) {
   if(led == 0) {
      leds = 0;
   } else {
      if (leds == (leds | led)) {   //If led is already on
         leds = leds ^ led;   // turn led off
      } else {
         leds = leds | led;   // else turn led on
      }
   }
   
   kbd_senddata(0xED);
   kbd_senddata(leds);         //update led status
}
My code for switching LEDs, maybe it helps you.

Re:Keyboard led problem

Posted: Wed Mar 30, 2005 8:28 am
by espenfjo
It's still not working, so i'm beginning to wonder if the problem could be Linux or maybe qemu/bochs/vmware

Re:Keyboard led problem

Posted: Wed Mar 30, 2005 11:45 am
by pini
You will probably not be able to switch on/off leds when using a emulator.
Try to make a "real" test to check if it works.

Re:Keyboard led problem

Posted: Wed Mar 30, 2005 4:37 pm
by B.E
Go to the following website and download the Ebook:
[link]http://webster.cs.ucr.edu/AoA/Windows/index.html[/link]

Goto chaptor 20. This will give you a full in depth tutorial on how to program the keyboard.

Re:Keyboard led problem

Posted: Thu Mar 31, 2005 4:52 am
by aladdin
here is the part of code of my keyboard driver to switch on/of keyboard leds, it works on all emulators and real machines

Code: Select all

...
static char kbdstatus = 0;
static short caps=0;   //variable to acces caps lock status
static short num=0;   //variable to access num lock status
...

void kbd_led(char status)
{
   int st;

   do {
      st = inb(0x64);
   } while (st&0x02);

   outb(0x60, 0x0ed);
   do {
      st = inb(0x64);
   } while (st&0x02);

   outb(0x60, status&0x07);

}

void switch_num_lock()
{
   if (num) num=0; else num=1; //is numlock on or off ?

   if(!(kbdstatus&NUM_LOCK))  
   {
      kbdstatus |= NUM_LOCK;
   }
   else    
      kbdstatus &= (CAPS_LOCK|SCROLL_LOCK);


   kbd_led(kbdstatus);   
}


void switch_caps_lock()
{
   if (caps) caps=0; else caps=1;
   if(!(kbdstatus&CAPS_LOCK)) 
   {
      kbdstatus |= CAPS_LOCK;
   }
   else    
      kbdstatus &= (NUM_LOCK|SCROLL_LOCK);


   kbd_led(kbdstatus);   
}

void switch_scroll_lock()
{

   if(!(kbdstatus&SCROLL_LOCK)) 
   {
      kbdstatus |= SCROLL_LOCK;
   }
   else    
      kbdstatus &= (NUM_LOCK|CAPS_LOCK);


   kbd_led(kbdstatus);   
}


Re:Keyboard led problem

Posted: Thu Mar 31, 2005 9:05 am
by espenfjo
Ok, it think i got it to work, it seems to work in vmware atleast. :)

Re:Keyboard led problem

Posted: Thu Mar 31, 2005 9:32 am
by proxy
this is more for aladdin, just wanted to let you know that your code could be MUCH simpler.

Code: Select all

void switch_num_lock()
{
  if (num) num=0; else num=1; //is numlock on or off ?

  if(!(kbdstatus&NUM_LOCK)) 
  {
      kbdstatus |= NUM_LOCK;
  }
  else   
      kbdstatus &= (CAPS_LOCK|SCROLL_LOCK);


  kbd_led(kbdstatus); 
}
coudl easily be written like this:

Code: Select all

void switch_num_lock()
{
  if (num) num=0; else num=1; //is numlock on or off ?

  if(!(kbdstatus&NUM_LOCK)) 
  {
      kbdstatus |= NUM_LOCK;
  }
  else   
      kbdstatus &= (~NUM_LOCK);


  kbd_led(kbdstatus); 
}
which could lead to a generic function doing thr real work and your "flip_whatever fuction just calling that with the right flag passed..but it get's better. XOR will flip bits just like you want so...

Code: Select all

void switch_num_lock()
{
  if (num) num=0; else num=1; //is numlock on or off ?

  kbdstatus ^= NUM_LOCK;

  kbd_led(kbdstatus); 
}
finally, what's with the conditional logic to invert a boolean?!

Code: Select all

void switch_num_lock()
{
  num = !num; //is numlock on or off ?
  kbdstatus ^= NUM_LOCK;
  kbd_led(kbdstatus); 
}
as you can see your solution is far more complicated than neccessary.

proxy