OSDev.org
https://forum.osdev.org/

Switching keyboard led
https://forum.osdev.org/viewtopic.php?f=1&t=10153
Page 1 of 1

Author:  Poseidon [ Sun Jan 09, 2005 2:53 pm ]
Post subject:  Switching keyboard led

How can I switch on/off the keyboard LEDs?

Now I'm asking, is there in some register or something like that saved which exception/interrupt has occured? It would be faster to program my exception handler then.

Author:  Brendan [ Sun Jan 09, 2005 3:50 pm ]
Post subject:  Re:Switching keyboard led

Hi,

Poseidon wrote:
How can I switch on/off the keyboard LEDs?


You could use something like:

Code:
%define LEDSCROLL 1
%define LEDNUMLOCK 2
%define LEDCAPS 4


;Set keyboard LED's
;________________________________________________
;
;Input
; al   LED's
;________________________________________________

setLeds:
   push ecx
   mov cl,0xed         ;Set status indicators
   call writeToDataPort
   call readFromDataPort      ;Wait until input buffer empty
   mov cl,al
   mov [LEDstates],cl
   call writeToDataPort
   pop ecx
   ret



Poseidon wrote:
Now I'm asking, is there in some register or something like that saved which exception/interrupt has occured? It would be faster to program my exception handler then.


For exceptions and software interrupts there isn't (for IRQ's there is, sort of).

To determine if an IRQ was the cause you can check the ISR (In Service Register) of both PIC chips (or the local APIC if you're using that instead). This doesn't always work as expected - it'll tell you which IRQs have been sent to the CPU but not which IRQs the CPU has sent to software (different CPUs "cache" some IRQs if interrupts are disabled).

To determine if it was a software interrupt you could look at the saved CS:EIP to see if either INTO, INT3 or INT N was the instruction that was executed before the interrupt. You'd need to be careful though - for e.g. if someone has a bug like "jmp <nowhere_in_particular>" that causes a page fault, and your exception handler tries to see what was running you'd also cause a page fault, which would cause a double fault (and probably a triple fault). To avoid this you'd need to check if the page was present and can be accessed first.

You'd also need to check if an IRQ was the cause first, otherwise you could get an IRQ immediately after a software interrupt and you'd think the software interrupt happened twice.

The information above is for general knowledge - I definately wouldn't suggest actually doing something like this.

Generally you'd determine which exception/interrupt occured by setting a different address for each one in the IDT. For IDT entries used by IRQs and exception handlers, set the protection flags so user level code can't generate them with a software interrupt (an attempt would result in a general protection fault). That way you can do something like:

Code:
int00:
    push eax
    mov eax,0
    jmp handler

int01:
    push eax
    mov eax,1
    jmp handler

int02:
    push eax
    mov eax,2
    jmp handler

...

intFF:
    push eax
    mov eax,255
    jmp handler


handler:       ;eax = interrupt number on entry
   ???
   pop eax
   iretd


That would be the fastest, simplest, most stable method...


Cheers,

Brendan

Author:  ASHLEY4 [ Sun Jan 09, 2005 9:20 pm ]
Post subject:  Re:Switching keyboard led

Hitting them with a hammer is a faster way to turn them off, but it's not so fast at turning them on again ;-).

\\\\||////
(@@)
ASHLEY4.

Batteries not included, Some assembly required.

Author:  distantvoices [ Mon Jan 10, 2005 3:09 am ]
Post subject:  Re:Switching keyboard led

well - one thing for sure: you 'd need solder & hot iron to get 'em running again. *rofl*

Author:  bubach [ Mon Jan 10, 2005 3:42 am ]
Post subject:  Re:Switching keyboard led

http://www.mega-tokyo.com/forum/index.p ... eadid=7009

Author:  Poseidon [ Mon Jan 10, 2005 11:49 am ]
Post subject:  Re:Switching keyboard led

i made this based on bubach's code:

Code:
void kbd_setled (BYTE status) {
   kbd_wait();

   p_outb(0x60, 0xED);

   kbd_wait();

   p_outb(0x60, status);

   kbd_wait();
}

void kbd_wait(void) {
__asm__ ("1:   inb   $0x64,%al\n" \
   "testb   $0x02,%al\n"\
   "jne   1b");
}


it doesn't work.. is it maybe because i didnt enable interrupots yet (didn't do a sti because my kernel crashes then)? or is there just a bug in the code..

thanx

Author:  Brendan [ Tue Jan 11, 2005 1:02 am ]
Post subject:  Re:Switching keyboard led

Hi,

I think the keyboard tries to send an "ack" after receiving the first command byte, which you'd need to read before the keyboard will do much.

Code:
void kbd_setled (BYTE status) {
???kbd_wait();

???p_outb(0x60, 0xED);

   kbd_read();

???kbd_wait();

???p_outb(0x60, status);

???kbd_wait();
}

void kbd_wait(void) {
__asm__ ("1:???inb???$0x64,%al\n" \
???"testb???$0x02,%al\n"\
???"jne???1b");
}

char kbd_read(void) {
__NASM??__("
   push eax
.l1:
   in al,statusPort
   test al,1      ;Is data ready?
   je .l1         ; no, wait
   in al,dataPort
   mov dl,al
   pop eax
   ret
");
}


Normally this byte would be read by the IRQ handler, but this isn't necessary (as long as something reads it).


Cheers,

Brendan

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/