Switching keyboard led

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Poseidon

Switching keyboard led

Post by Poseidon »

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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Switching keyboard led

Post by Brendan »

Hi,
Poseidon wrote: How can I switch on/off the keyboard LEDs?
You could use something like:

Code: Select all

%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: Select all

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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ASHLEY4

Re:Switching keyboard led

Post by ASHLEY4 »

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.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Re:Switching keyboard led

Post by distantvoices »

well - one thing for sure: you 'd need solder & hot iron to get 'em running again. *rofl*
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
User avatar
bubach
Member
Member
Posts: 1223
Joined: Sat Oct 23, 2004 11:00 pm
Location: Sweden
Contact:

Re:Switching keyboard led

Post by bubach »

"Simplicity is the ultimate sophistication."
http://bos.asmhackers.net/ - GitHub
Poseidon

Re:Switching keyboard led

Post by Poseidon »

i made this based on bubach's code:

Code: Select all

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
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Switching keyboard led

Post by Brendan »

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: Select all

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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply