#include #include #include unsigned char getmousestatus(void); int setleds(char leds); void interrupt (*tmrint_old)(void); void interrupt tmrint(void); void dly(int msec); void blinkled(unsigned char st); unsigned int cnt; unsigned char state; unsigned char blinkstate; unsigned int dly_cycles; const unsigned char led_lit = 0x1; const unsigned char led_dark = 0x0; union REGS inregs, outregs; int main(void) { while(!kbhit()) { /* check mouse status, program state depends on it */ state = getmousestatus(); switch(state) { case 0x1: { /* left button down, blink mode off, light * capslock and restart main loop */ blinkled(0x0); setleds(0x4); break; } case 0x2: { /* right button down, blink mode off, light * numlock only, restart main loop */ blinkled(0x0); setleds(0x2); break; } case 0x3: { /* both buttons down, blink mode on */ blinkled(0x1); break; } default: { /* both buttons up, blink mode off, * both leds dark, restart main loop */ blinkled(0x0); setleds(0x0); break; } } /* wait 50ms. mouse state can change during blink cycle, * so we need to be ready for it. five delay cycles * forces blinkled() to change led state -> ~2Hz rate */ dly(50); } return 0; } void blinkled(unsigned char st) { if(st) { /* about 250ms later and if led is dark, light led and restart * the 250ms wait period. if the led is lit, make it dark and * restart the waiting period. */ if((blinkstate == led_dark) && (dly_cycles >= 5)) { setleds(0x4); dly_cycles = 0; blinkstate = led_lit; } else if((blinkstate == led_lit) && (dly_cycles >= 5)) { setleds(0x0); dly_cycles = 0; blinkstate = led_dark; } } else { /* blink off */ dly_cycles = 0; blinkstate = led_dark; } } void dly(int msec) { /* set counter 0 of 8254 to 1000Hz rate */ outportb(0x43, 0x30); outportb(0x40, 0xa9); outportb(0x40, 0x04); /* store old interrupt vector, init cnt and * wait for it to reach msec */ tmrint_old = getvect(0x8); setvect(0x8, tmrint); cnt = 0; while(cnt < msec); /* restore old vector and value of counter 0 to 8254 */ setvect(0x8, tmrint_old); outportb(0x43, 0x30); outportb(0x40, 0xff); outportb(0x40, 0xff); /* dly_cycles is used in blinkled() to track how many times * we have been called */ dly_cycles++; } void interrupt tmrint(void) { disable(); cnt++; enable(); if(!(cnt % 55)) tmrint_old(); else outportb(0x20, 0x20); } unsigned char getmousestatus(void) { /* bios interrupt 33,3 is used to fetch mouse status */ unsigned char stat = 0x0; inregs.x.ax = 0x3; int86(0x33, &inregs, &outregs); stat = outregs.x.bx; return stat; } /* setleds() takes a char variable as parameter. * Bit values: * 7|6|5|4|3|2|1|0 * | | +--- scroll lock led (1 = on, 0 = off) * | +----- num lock led (1 = on, 0 = off) * +------- caps lock led (1 = on, 0 = off) * bits 3-7 MUST be zero. */ int setleds(char leds) { disable(); /* Prevent keyboard action */ outportb(0x60, 0xAD); /* Set 'change in progress' flag on*/ pokeb(0x40, 0x97, peekb(0x40, 0x97) | 0x40); /* Check if keyboard is ready to receive command */ if((inportb(0x64) & 2) != 0) { /* Keyboard wasn't ready */ printf("Keyboard not ready\n"); /* Send Resume to keyboard */ outportb(0x60, 0xF4); enable(); return 1; } /* Light leds */ do { outportb(0x60, 0xED); outportb(0x60, leds); /* Check the given result */ } while(inportb(0x60) != 0xFA); /* Enable keyboard action again */ outportb(0x60, 0xAE); /* Set 'change in progress' flag off*/ pokeb(0x40, 0x97, peekb(0x40, 0x97) & 0xBF); enable(); return 0; }