update for HEAD-2003021201
[reactos.git] / drivers / input / sermouse / mouse.c
1 /*
2
3  ** Mouse driver 0.0.3
4  ** Written by Jason Filby (jasonfilby@yahoo.com)
5  ** For ReactOS (www.sid-dis.com/reactos)
6
7  ** Note: The serial.o driver must be loaded before loading this driver
8
9  ** Known Limitations:
10  ** Only supports mice on COM port 1
11
12  ** Old Driver, We done build it. Just keep for History. (S.E.)
13
14 */
15
16 #include <ddk/ntddk.h>
17 #include <internal/mmhal.h>
18 #include <internal/halio.h>
19 /* #include <internal/hal/ddk.h> */
20 #include <funcs.h>
21
22 #define MOUSE_IRQ_COM1  4
23 #define MOUSE_IRQ_COM2  3
24
25 #define COM1_PORT       0x3f8
26 #define COM2_PORT       0x2f8
27
28 #define max_screen_x    79
29 #define max_screen_y    24
30
31 static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1;
32 static unsigned int MOUSE_COM=COM1_PORT;
33
34 static unsigned int     bytepos=0, coordinate;
35 static unsigned char    mpacket[3];
36 static signed int       mouse_x=40, mouse_y=12;
37 static unsigned char    mouse_button1, mouse_button2;
38 static signed int       horiz_sensitivity, vert_sensitivity;
39
40 BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
41 {
42         unsigned int mbyte=inb(MOUSE_COM);
43
44         // Synchronize
45         if((mbyte&64)==64) { bytepos=0; };
46
47         mpacket[bytepos]=mbyte;
48         bytepos++;
49
50         // Process packet
51         if(bytepos==3) {
52                 // Retrieve change in x and y from packet
53                 int change_x=((mpacket[0] & 3) << 6) + mpacket[1];
54                 int change_y=((mpacket[0] & 12) << 4) + mpacket[2];
55
56                 // Some mice need this
57                 if(coordinate==1) {
58                   change_x-=128;
59                   change_y-=128;
60                 };
61
62                 // Change to signed
63                 if(change_x>=128) { change_x=change_x-256; };
64                 if(change_y>=128) { change_y=change_y-256; };
65
66                 // Adjust mouse position according to sensitivity
67                 mouse_x+=change_x/horiz_sensitivity;
68                 mouse_y+=change_y/vert_sensitivity;
69
70                 // Check that mouse is still in screen
71                 if(mouse_x<0) { mouse_x=0; };
72                 if(mouse_x>max_screen_x) { mouse_x=max_screen_x; };
73                 if(mouse_y<0) { mouse_y=0; };
74                 if(mouse_y>max_screen_y) { mouse_y=max_screen_y; };
75
76                 // Retrieve mouse button status from packet
77                 mouse_button1=mpacket[0] & 32;
78                 mouse_button2=mpacket[0] & 16;
79
80                 bytepos=0;
81         };
82
83 };
84
85 void InitializeMouseHardware(unsigned int mtype)
86 {
87         char clear_error_bits;
88
89         outb_p(MOUSE_COM+3, 0x80); // set DLAB on
90         outb_p(MOUSE_COM, 0x60); // speed LO byte
91         outb_p(MOUSE_COM+1, 0); // speed HI byte
92         outb_p(MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse
93         outb_p(MOUSE_COM+1, 0); // set comm and DLAB to 0
94         outb_p(MOUSE_COM+4, 1); // DR int enable
95  
96         clear_error_bits=inb_p(MOUSE_COM+5); // clear error bits
97 };
98
99 int DetMicrosoft(void)
100 {
101         char tmp, ind;
102         int buttons=0, i;
103
104         outb_p(MOUSE_COM+4, 0x0b);
105         tmp=inb_p(MOUSE_COM);
106
107         // Check the first for bytes for signs that this is an MS mouse
108         for(i=0; i<4; i++) {
109                 while((inb_p(MOUSE_COM+5) & 1)==0) ;
110                 ind=inb_p(MOUSE_COM);
111                 if(ind==0x33) buttons=3;
112                 if(ind==0x4d) buttons=2;
113         };
114
115         return buttons;
116 };
117
118 int CheckMouseType(unsigned int mtype)
119 {
120         unsigned int retval=0;
121
122         InitializeMouseHardware(mtype);
123         if(mtype==2) retval=DetMicrosoft();
124         if(mtype==3) {
125                 outb_p(MOUSE_COM+4, 11);
126                 retval=3;
127         };
128         outb_p(MOUSE_COM+1, 1);
129
130         return retval;
131 };
132
133 void ClearMouse(void)
134 {
135         // Waits until the mouse calms down but also quits out after a while
136         // in case some destructive user wants to keep moving the mouse
137         // before we're done
138
139         unsigned int restarts=0, i;
140         for (i=0; i<60000; i++)
141         {
142           unsigned temp=inb(MOUSE_COM);
143           if(temp!=0) {
144             restarts++;
145             if(restarts<300000) {
146                     i=0;
147             } else
148             {
149                     i=60000;
150             };
151           };
152         };
153 };
154
155 void InitializeMouse(void)
156 {
157         int mbuttons=0, gotmouse=0;
158         ULONG MappedIrq;
159         KIRQL Dirql;
160         KAFFINITY Affinity;
161         PKINTERRUPT IrqObject;
162
163         horiz_sensitivity=2;
164         vert_sensitivity=3;
165
166         // Check for Microsoft mouse (2 buttons)
167         if(CheckMouseType(2)!=0)
168         {
169                 gotmouse=1;
170                 DbgPrint("Microsoft Mouse Detected\n");
171                 ClearMouse();
172                 coordinate=0;
173         };
174
175         // Check for Microsoft Systems mouse (3 buttons)
176         if(gotmouse==0) {
177           if(CheckMouseType(3)!=0)
178           {
179                 gotmouse=1;
180                 DbgPrint("Microsoft Mouse Detected\n");
181                 ClearMouse();
182                 coordinate=1;
183           };
184         };
185
186         if(gotmouse==0) {
187                 DbgPrint("No Mouse Detected!\n");
188         } else {
189                 MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ,
190                                                   &Dirql, &Affinity);
191
192                 IoConnectInterrupt(&IrqObject, microsoft_mouse_handler, NULL,
193                                    NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
194                                    Affinity, FALSE);
195         };
196 };
197
198 // For test purposes only
199 unsigned char get_text_char(int x, int y)
200 {
201         unsigned char getchar;
202         char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
203         getchar=*vidmem;
204         return getchar;
205 };
206
207 // For test purposes only
208 unsigned char get_text_color(int x, int y)
209 {
210         unsigned char getcolor;
211         char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
212         vidmem++;
213         getcolor=*vidmem;
214         return getcolor;
215 };
216
217 // For test purposes only
218 void put_text_char(int x, int y, unsigned char putchar[2])
219 {
220         char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
221         *vidmem=putchar[0];
222         vidmem++;
223         *vidmem=putchar[1];
224 };
225
226 // For test purposes only
227 void test_mouse(void)
228 {
229   static int i=0, forcechange=0;
230   static int old_x=40, old_y=12;
231   static unsigned char old_cursor[2], new_cursor[2];
232
233   DbgPrint("Testing mouse...");
234
235   old_cursor[0]=' ';
236   old_cursor[1]=7;
237   new_cursor[0]='Û';
238   new_cursor[1]=15;
239
240   old_cursor[0]=get_text_char(mouse_x, mouse_y);
241   old_cursor[1]=get_text_color(mouse_x, mouse_y);
242   put_text_char(mouse_x, mouse_y, new_cursor);
243
244   while(i!=1)
245   {
246     if(mouse_button1!=0) { new_cursor[1]=10; mouse_button1=0; forcechange=1; };
247     if(mouse_button2!=0) { new_cursor[1]=12; mouse_button2=0; forcechange=1; };
248
249     if((mouse_x!=old_x) || (mouse_y!=old_y) || (forcechange==1)) {
250         forcechange=0;
251
252         put_text_char(old_x, old_y, old_cursor);
253         old_cursor[0]=get_text_char(mouse_x, mouse_y);
254         old_cursor[1]=get_text_color(mouse_x, mouse_y);
255         put_text_char(mouse_x, mouse_y, new_cursor);
256
257         old_x=mouse_x;
258         old_y=mouse_y;
259     };
260   };
261 };
262
263 NTSTATUS STDCALL
264 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
265 {
266         DbgPrint("Mouse Driver 0.0.3\n");
267         InitializeMouse();
268         test_mouse();
269
270         return(STATUS_SUCCESS);
271 };
272