batman@watsci.uwaterloo.ca (Marcell Stoer) (01/23/90)
First of all I'd like to thank everyone for their input, this goes to: Tom Hill late@Sun.Com Darren Porter porter@cssexb.ccs.csus.edu John Nelson jpn@genrad.com Brian Helterline brainh@hpcvia.cv.hp.com Stuart Kemp kemp@umn-cs.cs.umn.edu Raymond Chen raymond@math.berkley.edu Robert Adsett semicon@watsci.waterloo.edu I acquired a book call _MSDOS Extentions Programmers quick Reference_ by Microsoft Press, which contains all the interrupt calls for the expanded and extended memory, CD-ROM and the Microsoft Mouse (which is very much compatible with Logitech). I've found that it seems to have all the information I need. There are other more extensive books, with routine samples in C and some even supply a diskette withe Demos (I think its one by Microsoft Press). Here is the summary, it is quite long, since Tom Hill (reply 1) was generous enough to include some sample mouse testing routines (in C). I placed his last. You may want to save this and read it later. thanks, Marcell. ----------------------------- Reply 2, Darren Porter writes : Try the _Microsoft Mouse Programmer's Reference_ by Microsoft press. I wrote my own library of mouse functions in Pascal through this book. It has examples in C also. I'm not sure of the compatibility with the Logitech mouse, though. Are they compatible? I know my library works with an AT&T mouse that uses the Logitech driver... Reply 3, (jpn@genrad.com) John Nelson The easiest (and most portable) way to write code that uses a mouse is to install the mouse "driver", then use the standard mouse software interface. All mouse functions are accessed via "int 33" when a driver is active. There are too many functions for me to list them here. The mouse interface is documented in MANY places. If you don't have a copy of "Advanced MSDOS programming" by Ray Duncan, published by Microsoft Press, then I recommend it. -- Reply 4 , Brian Helterline (brianh@hpcvia.cv.HP.COM): To access a mouse in C, you need to use int86() (MSC 5.1). The interrupt you are interested in is INT 0x33 (BIOS mouse driver that is compatible with MS mouse). By passing the correct info, you can turn on the mouse, read its position, determine status of buttons, position mouse, etc. Check out a system BIOS manual for details. I wrote a few basic routines to do this stuff. If you are using MSC and would like them, let me know & I'll email them to you. Another approach is to use a canned package that has mouse support built into its library. All you have to do is include their library at compile time & use their ready-made mouse functions. These functions use the same idea as above (int 0x33). One such company is: Greenleaf Software Inc. 16479 Dallas Parkway, Suite 570 Bent Tree Tower Two Dallas, TX 75248 (214) 248-2561 They have a lot more than the basic functions I wrote, but they also cost more. NOTE: I am not associated with or endorsing Greenleaf Software Inc. or any of its products. --------------------------- Reply 5, Stuart Kemp writes : The mouse stuff is all available via int 33h. The entire list of options are available in some books; otherwise look in the list of interrupts that appears here sometimes. (As mainatined by Ralf Brown). Is available via anon ftp from cs.cmu.edu (128.2.222.173). Look in directory /afs/cs/user/ralf/pub (you must cd to that directory all at once) File is interrup.zip. ----------------------------- Reply 6, (raymond@math.berkeley.edu) Raymond Chen writes : Grab the Interrupt List and read about Int 33h. That's where all the mouse information comes from. --------------------- NOTE : Although This was the first reply, I placed it last due to its length. Reply 1 : From: late@Sun.COM (Tom Hill) There are several books out that will tell you about the mouse. My favorite is Advanced MS-DOS programming by ray duncan, which is one of the best books on programming the pc. Covers ms-dos, some bios stuff, mouse, EMS. Good book. Microsoft press also has a book on programming the mouse too. Let's see, I started writing a program to test a mouse driver, I'll tack it on the end. It's not really done, but if you're like me you'd rather have something to play with now, until you can find the books. It should give you some idea about how to access the driver. Remember I just started this, bugs are virtually guaranteed!!! Note : In the example mouse program I sent, there was a call to 'mouse_disable' (int 33, function 31). It turns out this turns off the mouse a little more thoroughly than I intended, and you should probably take the call to mouse_disable out, & replace it with a call to mouse_reset. I had assumed that reseting the mouse would take it out of the disabled state. WRONG! So after you do a disable, most applications won't even notice you have a mouse. You have to do an enable (int 33, ax=32) before the mouse will work again. Or reboot. /* * Program to test the functionaliy of a microsoft compatible mouse driver * This program must be compiled under TurboC 2.0. Since one of the functions * below is called at interrupt time by the mouse irq service routine, the * Compiler options option/compiler/codegen/test stack and also * option/compiler/optimize/register vars must be off for the program to work */ /*------------------------------------------------------------------------*/ /* This routine provides some minimal mouse testing. */ /*------------------------------------------------------------------------*/ /* ------------------- Include files -------------------------------------*/ #include <conio.h> #include <ctype.h> #include <dos.h> #include <stdio.h> #include <stdlib.h> /* ------------------- Constant declarations -----------------------------*/ #define N_FUNCTIONS 36 /* Number of functions supported by Microsoft */ /* Mouse driver version 6 (current at this time) */ #define SCREEN_ADDRESS 0xB8000 /* ------------------- Type declarations ---------------------------------*/ /* ------------------- Local function prototypes -------------------------*/ static int mouse_test_0(void); static int mouse_test_1(void); static int mouse_test_2(void); static int mouse_test_3(void); static int mouse_test_4(void); static int mouse_test_5(void); static int mouse_test_6(void); static int mouse_test_7(void); static int mouse_test_8(void); static int mouse_test_9(void); static int mouse_test_10(void); static int mouse_test_11(void); static int mouse_test_12(void); static char get_key(void); static int mouse_position(void); static int mouse_reset(void); static void mouse_disable(void); static void mouse_setp(int x,int y); static void mouse_getp(int *x,int *y); static int test_handlers(void); static void usage(void); static void record_results(int function_number,int result); /* ------------------- Global data ---------------------------------------*/ /* ------------------- Data local to this module -------------------------*/ static int data_segment; struct { int run; /* Was this test run ? */ int status; /* Did function succeed (1) or fail (0) */ } results[N_FUNCTIONS]; static int (*functions[N_FUNCTIONS])(void) = { mouse_test_0, mouse_test_1, mouse_test_2, mouse_test_3, mouse_test_4, mouse_test_5, mouse_test_6, mouse_test_7, mouse_test_8, mouse_test_9, mouse_test_10, mouse_test_11, mouse_test_12, }; int main() { int test; data_segment = _DS; /* For mouse event handler */ usage(); record_results(0,mouse_test_0()); if (!results[0].status) { printf("No mouse found\n"); return(0); } for (test = 0; test< N_FUNCTIONS; test++) { if (functions[test] == NULL) { printf("Test #%3d not implemented\n",test); continue; } else { record_results(test,(*functions[test])()); } } mouse_disable(); clrscr(); for (test = 0; test < N_FUNCTIONS; test++) { if (results[test].run) { printf("Test #%3d ",test); if (results[test].status) printf("passed\n"); else printf("FAILED!!!!!\n"); } } printf("Done.\n"); return(1); } static void record_results(int function_number,int result) { if (results[function_number].run) results[function_number].status &= result; else results[function_number].status = result; results[function_number].run = 1; } /* Throw away one keystroke. Function keys & the like read a two characters */ static void eat_key(void) { int c; c = getch(); if (c == 0) getch(); } static void usage(void) { clrscr(); printf("This program tests the basic functionality of a\n"); printf("Microsoft compatible mouse driver\n"); printf("\nPlease follow the directions you see on the screen\n"); printf("Press any key to continue\n"); while (!kbhit()) ; eat_key(); } /* Handler for mouse events, called directly from mouse interrupt handler. */ static void far mouse_info() { char far * screen = (char far *)0xb8000000L; int ax = _AX; int x; int mask = 1; int bitcount = 0; _DS = data_segment; for (x =0; x < 0x5; x++) { if (mask & ax) { screen[2*(x+3)*80] = '1'; bitcount++; } else { screen[2*(x+3)*80] = '0'; } mask <<= 1; } /* Test for odd conditions. Multiple events on one tick (okay i think?) */ /* or zero events, which I think should not happen */ if (bitcount > 1) screen[2*(x +3)*80] = 'Y'; x++; if (bitcount == 0) screen[2*(x +3)*80] = 'Y'; x++; screen[2*(x +3)*80]++; /* Provided visual indicator that */ /* we are being called, even if the */ /* button state is not changing */ } /* Turn the mouse driver off */ static void mouse_disable() { struct REGPACK reg; reg.r_ax = 31; intr(0x33,®); } static void mouse_display(void) { struct REGPACK reg; reg.r_ax = 1; intr(0x33,®); } static void mouse_hide(void) { struct REGPACK reg; reg.r_ax = 2; intr(0x33,®); } /* Set the mouse position */ static void mouse_setp(int x,int y) { struct REGPACK reg; reg.r_ax = 4; reg.r_cx = x; reg.r_dx = y; intr(0x33,®); } /* Get the position of the mouse */ static void mouse_getp(int *x,int *y) { struct REGPACK reg; reg.r_ax = 3; intr(0x33,®); if (reg.r_bx != 0) printf("Buttons are down.\n"); *x = reg.r_cx; *y = reg.r_dx; } static char get_key(void) { struct REGPACK reg; reg.r_ax = 0; intr(0x16,®); return(reg.r_ax & 0xff); } static void mouse_int(int ax,int bx,int cx,int dx,int es) { struct REGPACK reg; reg.r_ax = ax; reg.r_bx = bx; reg.r_cx = cx; reg.r_dx = dx; reg.r_es = es; intr(0x33,®); } /* Since code to test functions 5 & 6 is almost identical, this * function handles both, based on the paramters passed */ static int mouse_press_release( int function, /* Five for press test, six for release test */ int button /* 0,1,2 left, right center. We emulate a 2 button */ /* mouse, so there is no center */ ) { struct REGPACK reg; char *msg[2] = {"presses","releases"}; char *button_names[3] = {"Left","Right","Center"}; clrscr(); if (!mouse_reset()) return(0); mouse_display(); if ((function != 5) && function !=6) return(0); printf("Test function %d, count button %s\n",function,msg[function-5]); printf("It will sample the %s button at two second intervals\n",button_names[button]); printf("And report count, location & state.\n"); printf("Press any key to when you are done with this test.\n"); while (!kbhit()) { reg.r_ax = function; reg.r_bx = button; intr(0x33,®); printf("%d %s ",reg.r_bx,msg[function-5]); printf("at (%3d:%3d) ",reg.r_cx,reg.r_dx); printf("buttons down are %5s %5s %6s\n", (reg.r_ax & 1) ? "Left":"", (reg.r_ax & 2) ? "Right":"", (reg.r_ax & 4) ? "Center":"" ); delay(1500); } eat_key(); return(1); } static int mouse_reset() { struct REGPACK reg; reg.r_ax = 0; intr(0x33,®); return(reg.r_ax == 0xFFFF); } static void set_graph_mode(void) { struct REGPACK regs; regs.r_ax = 0x0006; intr(0x10,®s); directvideo = 0; } static void set_text_mode(void) { struct REGPACK regs; directvideo = 1; regs.r_ax = 0x0003; intr(0x10,®s); } static void get_pos_and_motion(int *x,int *y,int *dx,int *dy) { struct REGPACK regs; regs.r_ax = 3; intr(0x33,®s); *x = regs.r_cx; *y = regs.r_dx; regs.r_ax = 0x0B; intr(0x33,®s); *dx = regs.r_cx; *dy = regs.r_dx; } /* * Test functions for each mouse function follow in numerical order */ /* Mouse function 0 test, initialization & number of buttons */ static int mouse_test_0(void) { struct REGPACK reg; reg.r_ax = 0; intr(0x33,®); if (reg.r_ax != 0xFFFF) { printf("Mouse support not available\n"); return(0); } if (reg.r_bx != 2) { printf("Wrong number of mouse buttons.\n"); return(0); } return(1); } static int mouse_test_1() { int c; clrscr(); mouse_reset(); printf("This function tests cursor display & hide functionality\n"); printf("The cursor should initialize to hidden\n"); printf("Is the cursor HIDDEN now? (y or n)\n"); do { c = getch(); c = toupper(c); } while ((c != 'Y') && (c != 'N')); if (c == 'N') { printf("Error, should initialize to hidden\n"); printf("Press any key to continue\n"); eat_key(); return(0); } mouse_display(); printf("Is the cursor VISIBLE now? (Y or N)?\n"); do { c = getch(); c = toupper(c); } while ((c != 'Y') && (c != 'N')); if (c == 'N') { printf("Error, display (function 1) did not work\n"); printf("Press any key to continue\n"); eat_key(); return(0); } mouse_hide(); printf("Is the cursor HIDDEN now? (Y or N)?\n"); do { c = getch(); c = toupper(c); } while ((c != 'Y') && (c != 'N')); if (c == 'N') { printf("Error, hide (function #2) did not work\n"); printf("Press any key to continue\n"); eat_key(); return(0); } printf("Test passed, press any key to continue\n"); eat_key(); return(1); } static int mouse_test_2() { return(mouse_test_1()); } static int mouse_test_3() { printf("Function not implemented\n"); printf("Test considered failed, press any key\n"); eat_key(); return(0); } /* Set the mouse position, then try to read it back */ static int mouse_test_4(void) { #define N_POINTS 6 int index,x_read,y_read,x_set,y_set; int c; mouse_reset(); clrscr(); printf("Testing function 4, set mouse position\n"); printf("It will set the position %d times, and prompt you to verify\n",N_POINTS); printf("Press any key to continue\n"); eat_key(); for (index = 0; index < N_POINTS; index++) { x_set = random(640); y_set = random(200); clrscr(); mouse_display(); printf("Moving to %3d,%3d\n",x_set,y_set); mouse_setp(x_set,y_set); mouse_getp(&x_read,&y_read); /* * If we are in text mode on a PC these numbers should be * rounded. In graphics mode, or using the sunview cursor * These numbers are not rounded. I think we should round * the numbers for the sunview cursor, so we look more like * a PC. */ if (1) { x_set &= ~7; /* In text mode, mouse position is rounded */ y_set &= ~7; } if ((x_read != x_set) || (y_read != y_set)) { printf("Position reported does not match position set\n"); printf("Test failed, press any key\n"); eat_key(); return(0); } printf("Does the position look about right?\n"); do { c = getch(); c = toupper(c); } while ((c != 'Y') && (c != 'N')); if (c == 'N') { printf("Error, sunview cursor not moved to correct place.\n"); printf("Press any key to continue\n"); eat_key(); return(0); } } return(1); #undef N_POINTS } static int mouse_test_5() { int result; result = mouse_press_release(5,0); result &= mouse_press_release(5,1); return(result); } static int mouse_test_6() { int result; result = mouse_press_release(6,0); result &= mouse_press_release(6,1); return(result); } /* Test horizontal mouse motion limits, funtion 7 */ static int mouse_test_7() { int min=320; int max=480; clrscr(); mouse_test_0(); mouse_display(); printf("Testing function 7, horizontal motion limits\n"); printf("Limiting motion to the range %3d to %3d\n",min,max); printf("Press any key when done\n"); mouse_int(7,0,min,max,0); do { } while (!kbhit()); eat_key(); return(1); } /* Test vertical motion limitations function 8 */ static int mouse_test_8() { int min=0; int max=100; clrscr(); mouse_test_0(); mouse_display(); printf("Testing function 8, vertical motion limits\n"); printf("Limiting motion to the range %3d to %3d\n",min,max); printf("Press any key when done\n"); mouse_int(8,0,min,max,0); do { } while (!kbhit()); eat_key(); return(1); } /* * Check function 9, set graphics pointer shape */ static int mouse_test_9() { int mask[32] = /* and */ {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0, /* or */ 0x0000,0x7FFE,0x4000,0x4000, 0x4000,0x4000,0x4000,0x4000, 0x7f00,0x4000,0x4000,0x4000, 0x4000,0x4000,0x4000,0x0000}; clrscr(); set_graph_mode(); mouse_reset(); mouse_int(9,2,2,(int)mask,_DS); mouse_int(1,0,0,0,0); /* display the mouse */ printf("Set the mouse shape. It should look like a \n"); printf("large capital F, no reflections or rotations.\n"); while (!kbhit()) ; eat_key(); set_text_mode(); return(1); } static int mouse_test_10() { printf("Function not implemented\n"); printf("Test considered failed, press any key\n"); eat_key(); return(0); } /* Read the mouse motion counters, and see if they correlate with the */ /* mouse position & mickey to pixel ratios */ static int mouse_test_11() { struct REGPACK reg; int x,y, /* Current mouse position */ x1,y1, /* Previous recorded mouse position */ dx,dy, /* Mickeys since last read. */ x_mickey=8,y_mickey=8; /* Mickeys per 8 pixels */ mouse_test_0(); mouse_int(0x0F,0,x_mickey,y_mickey,0); x_mickey /= 8; /* convert to mickeys per pixel */ y_mickey /= 8; /* ditto */ clrscr(); set_graph_mode(); mouse_int(1,0,0,0,0); printf("Check functions 3, 11 and 15, and 15\n"); printf("Please move the mouse , then click, several times\n"); printf("Press any key when you are done.\n"); get_pos_and_motion(&x1,&y1,&dx,&dy); delay(2000); do { delay(1000); get_pos_and_motion(&x,&y,&dx,&dy); printf("New x: %3d, old x: %3d diff: %3d, xmickeys = %3d\n",x,x1,x-x1,dx); printf("New y: %3d, old y: %3d diff: %3d, ymickeys = %3d\n",y,y1,y-y1,dy); if ( ((x-x1)*x_mickey != ((dx / x_mickey) * x_mickey) ) ) goto exit; if ( ((y-y1)*y_mickey != ((dy / y_mickey) * y_mickey) ) ) goto exit; x1 = x; y1 = y; } while (!kbhit()); set_text_mode(); return(1); exit: printf("Test failed - press any key\n"); eat_key(); set_text_mode(); return(0); } static int mouse_test_12() { struct REGPACK reg; long fp; reg.r_ax = 0xC; reg.r_cx = 0xFF; fp = (long)mouse_info; reg.r_dx = (int)fp; reg.r_es = (int) (fp >> 16); intr(0x33,®); clrscr(); printf("\nTest event handlers\nPress a key when done.\n"); printf(" Movement\n"); printf(" Left pressed\n"); printf(" Left released\n"); printf(" Right pressed\n"); printf(" Right released\n"); printf(" Multiple events, one tick (Cumulative)\n"); printf(" Zero events, one tick. Error if this occurs.\n"); printf(" Counter. Increments on every call to event handler.\n"); while (!kbhit()) ; return(1); } Reply 2: From: porterd@cssexb.ccs.csus.edu@cssexb.ccs.csus.edu (darren porter) Try the _Microsoft Mouse Programmer's Reference_ by Microsoft press. I wrote my own library of mouse functions in Pascal through this book. It has examples in C also. I'm not sure of the compatibility with the Logitech mouse, though. Are they compatible? I know my library works with an AT&T mouse that uses the Logitech driver... Reply 3: From: jpn@genrad.com (John P. Nelson) The easiest (and most portable) way to write code that uses a mouse is to install the mouse "driver", then use the standard mouse software interface. All mouse functions are accessed via "int 33" when a driver is active. There are too many functions for me to list them here. The mouse interface is documented in MANY places. If you don't have a copy of "Advanced MSDOS programming" by Ray Duncan, published by Microsoft Press, then I recommend it. Reply 4: From: brian_helterline <brianh@hpcvia.cv.hp.com> To access a mouse in C, you need to use int86() (MSC 5.1). The interrupt you are interested in is INT 0x33 (BIOS mouse driver that is compatible with MS mouse). By passing the correct info, you can turn on the mouse, read its position, determine status of buttons, position mouse, etc. Check out a system BIOS manual for details. I wrote a few basic routines to do this stuff. If you are using MSC and would like them, let me know & I'll email them to you. Another approach is to use a canned package that has mouse support built into its library. All you have to do is include their library at compile time & use their ready-made mouse functions. These functions use the same idea as above (int 0x33). One such company is: Greenleaf Software Inc. 16479 Dallas Parkway, Suite 570 Bent Tree Tower Two Dallas, TX 75248 (214) 248-2561 They have a lot more than the basic functions I wrote, but they also cost more. NOTE: I am not associated with or endorsing Greenleaf Software Inc. or any of its products. Reply 5: From: "Stuart R. Kemp" <kemp@umn-cs.cs.umn.edu> The mouse stuff is all available via int 33h. The entire list of options are available in some books; otherwise look in the list of interrupts that appears here sometimes. (As mainatined by Ralf Brown). Is available via anon ftp from cs.cmu.edu (128.2.222.173). Look in directory /afs/cs/user/ralf/pub (you must cd to that directory all at once) File is interrup.zip. Reply 6: From raymond@math.berkeley.edu Wed Jan 17 12:17:21 1990 Grab the Interrupt List and read about Int 33h. That's where all the mouse information comes from. -- Marcell BITNET : Batman@Watsci.uwaterloo.ca I can't believe the news today, I can't close my eyes and make it go away!" -U2