Here's the attempt to translate my article to english (making it brief)... The text is abour PS/2 mouse (USB or not it works!) and uses the old Turbo C 2.01, which is easy to transpose to real mode asm...
The PS/2 Mouse is attached to IRQ12, so we need a handler:
#define CLAMP(x,_min,_max) \
{ \
if ((x) < (_min)) (x) = (_min); else \
if ((x) > (_max)) (x) = (_max); \
}
/* Screen max x-pos and x-pos (starting from 0). */
#define MAXX 79
#define MAXY 24
/* For testing purposes I'm using (39,12) as the initial coordinates.
the middle of the text mode 3 screen. */
char buttons;
int mouse_x = 39;
int mouse_y = 12;
int mouse_ok = 0; // if we have all 3 above data ready, 1 - otherwise, 0.
static int first_time = 1;
void interrupt irq12isr(void)
{
/* mouse will provide coordinates and
button status, one by one, each time it requests an
interruption... We'll store in this buffer...
buffer[1] is x-delta, buffer[2] is y-delta and buffer[0] are the buttons. */
static char buffer[3];
static int pos = 0;
/* I don't know why, but we must discard the first data. */
if (first_time)
{
first_time = 0;
inportb(0x60);
goto exit_isr;
}
buffer[pos++] = inportb(0x60);
if (pos == 3)
{
pos = 0;
/* I want just the button states... */
buttons = buffer[0] & 7;
/* Divide delta by to to make delta less sensible. */
mouse_x += buffer[1] / 2;
mouse_y -= buffer[2] / 2;
/* We don't want the mouse cursor out of the screen,
won't we? */
CLAMP(mouse_x, 0, MAXX);
CLAMP(mouse_y, 0, MAXY);
mouse_ok = 1;
}
exit_isr:
/* Sends EOI to the PICs */
outportb(0xa0, 0x20);
outportb(0x20, 0x20);
}
Now, we need to initialize the Interrupt vector 0x12, send commands to the mouse so it will generate interrupt requests, unmask the secondary PIC IRQ 12... Below, mouse_uninit() is listed as well...
static void interrupt (far *oldisr)(void);
void mouse_init(void)
{
unsigned char kbdc_cw;
disable();
mask_irqs();
// Adjust the new ISR for IRQ 12 on vector 0x74.
oldisr = getvect(0x74);
setvect(0x74, irq12isr);
// Disable primary and auxiliar devices on KBDC.
kbdc_wait(1, 0); outportb(0x64, 0xad);
kbdc_wait(1, 0); outportb(0x64, 0xa7);
// Turn on IRQ12 on KBDC.
kbdc_wait(1, 0); outportb(0x64, 0x20);
kbdc_wait(0, 0); kbdc_cw = inportb(0x60) | 2;
kbdc_wait(1, 0); outportb(0x64, 0x60);
kbdc_wait(1, 0); outportb(0x60, kbdc_cw);
// Now we can re-enable the keyboard...
kbdc_wait(1, 0); outportb(0x64, 0xae);
// ... and enable mouse (auxiliar device).
kbdc_wait(1, 0); ourtporb(0x64, 0xa8);
// Configure mouse...
mouse_write(0xff); // reset and waits for 0xaa.
while (mouse_read() != 0xaa);
mouse_write(0xf6); // puts mouse on default mode.
while (mouse_read() != 0xfa); // waits for ACK.
mouse_write(0xf4); // enable mouse streamming mode...
while (mouse_read() != 0xfa); // waits for ACK.
kbdc_wait(1, 0); // Waits for mouse readiness...
unmask_irqs();
enable();
}
void mouse_uninit(void)
{
unsigned char kbdc_cw;
disable();
// Mask IRQ 12.
outportb ( 0xa1, inportb ( 0xa1 ) | ( 1 << 4 ) );
// Desable mouse.
mouse_write ( 0xf5 );
while ( mouse_read() != 0xfa ); // Ack
// Disable auxiliary device.
kbdc_wait ( 1, 0 ); outportb ( 0x64, 0xa7 );
// Disable IRQ12 on KBDC.
kbdc_wait ( 1, 0 ); outportb ( 0x64, 0x20 );
kbdc_wait ( 0, 0 ); kbdc_cw = ( inportb ( 0x60 ) & ~2 );
kbdc_wait ( 1, 0 ); outportb ( 0x64, 0x60 );
kbdc_wait ( 1, 0 ); outportb ( 0x60, kbdc_cw );
// Set the old IRQ 12 vector 0x74...
setvect ( 0x74, oldvect );
enable();
}
The mask_irqs() and unmask_irqs() just masks (disable) and unmasks (enable), respectively, IRQ 1 (keyboard) and IRQ 12 (mouse). enable() and disable() are "CLI" and "STI" instructions.
Here are mouse_read(), mouse_write() and kbdc_wait() routines:
/* buffer = 0 (output) or 1 (input).
auxiliary = 0 (keyboard), 1 (mouse). */
void kbdc_wait(int buffer, int auxiliary)
{
int count = 0;
// tries 65536 times...
while (--count)
if (!buffer)
{
// Exit if we have output data.
if (inportb(0x64) & (auxiliary ? 0x21 : 0x01))
break;
}
else
// Input is free?
if (!(inportb(0x64) & 0x02))
break;
}
void mouse_write(unsigned char data)
{
kbdc_wait(1, 0); outportb(0x64, 0xd4);
kbdc_wait(1, 0); outportb(0x60, data);
}
unsigned char mouse_read(void)
{ kbdc_wait(0, 1); return inportb(0x60); }
Here a test program fragmetn to test it:
void cursor(int x, int y, int draw)
{
char far *ptr = MK_FP(0xb800, 160*y+2*x+1);
*p = draw ? 0xf0 : 7;
}
void main(void)
{
int oldx = mouse_x;
int oldy = mouse_y;
clrscr();
cputs("Hit any key to stop...");
mouse_init();
cursor(oldx, oldy, 1); // show cursor.
while (!kbhit())
if (mouse_ok)
{
cursor(oldx, oldy, 0); // hide cursor
cursor(oldx = mouse_x, oldy = mouse_y, 1); // show cursor.
mouse_ok = 0; // we're done until next update...
}
mouse_uninit();
}
The result is in the attachment (GIF animated)...
I hope it helps!