1 |
|
---|
2 | /*++
|
---|
3 |
|
---|
4 | Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
|
---|
5 |
|
---|
6 | Module Name:
|
---|
7 |
|
---|
8 | moudep.c
|
---|
9 |
|
---|
10 | Abstract:
|
---|
11 |
|
---|
12 | The initialization and hardware-dependent portions of
|
---|
13 | the Intel i8042 port driver which are specific to
|
---|
14 | the auxiliary (PS/2 mouse) device.
|
---|
15 |
|
---|
16 | Environment:
|
---|
17 |
|
---|
18 | Kernel mode only.
|
---|
19 |
|
---|
20 | Notes:
|
---|
21 |
|
---|
22 | NOTES: (Future/outstanding issues)
|
---|
23 |
|
---|
24 | - Powerfail not implemented.
|
---|
25 |
|
---|
26 | - Consolidate duplicate code, where possible and appropriate.
|
---|
27 |
|
---|
28 | Revision History:
|
---|
29 |
|
---|
30 | --*/
|
---|
31 |
|
---|
32 | // VBOX begin
|
---|
33 | // VBOX backdoor logging
|
---|
34 | //#define LOG_ENABLED
|
---|
35 | #include <VBox/err.h>
|
---|
36 | // VBOX end
|
---|
37 |
|
---|
38 | #include "stdarg.h"
|
---|
39 | #include "stdio.h"
|
---|
40 | #include "string.h"
|
---|
41 | #include "ntddk.h"
|
---|
42 | #include "i8042prt.h"
|
---|
43 | #include "i8042log.h"
|
---|
44 |
|
---|
45 | //
|
---|
46 | // Use the alloc_text pragma to specify the driver initialization routines
|
---|
47 | // (they can be paged out).
|
---|
48 | //
|
---|
49 |
|
---|
50 | #ifdef ALLOC_PRAGMA
|
---|
51 | #pragma alloc_text(INIT,I8xMouseConfiguration)
|
---|
52 | #pragma alloc_text(INIT,I8xMousePeripheralCallout)
|
---|
53 | #pragma alloc_text(INIT,I8xInitializeMouse)
|
---|
54 | #pragma alloc_text(INIT,I8xFindWheelMouse)
|
---|
55 | #endif
|
---|
56 |
|
---|
57 | |
---|
58 |
|
---|
59 | BOOLEAN
|
---|
60 | I8042MouseInterruptService(
|
---|
61 | IN PKINTERRUPT Interrupt,
|
---|
62 | IN PVOID Context
|
---|
63 | )
|
---|
64 |
|
---|
65 | /*++
|
---|
66 |
|
---|
67 | Routine Description:
|
---|
68 |
|
---|
69 | This is the interrupt service routine for the mouse device.
|
---|
70 |
|
---|
71 | Arguments:
|
---|
72 |
|
---|
73 | Interrupt - A pointer to the interrupt object for this interrupt.
|
---|
74 |
|
---|
75 | Context - A pointer to the device object.
|
---|
76 |
|
---|
77 | Return Value:
|
---|
78 |
|
---|
79 | Returns TRUE if the interrupt was expected (and therefore processed);
|
---|
80 | otherwise, FALSE is returned.
|
---|
81 |
|
---|
82 | --*/
|
---|
83 |
|
---|
84 | {
|
---|
85 | PDEVICE_EXTENSION deviceExtension;
|
---|
86 | PDEVICE_OBJECT deviceObject;
|
---|
87 | LARGE_INTEGER tickDelta, newTick;
|
---|
88 | UCHAR previousButtons;
|
---|
89 | UCHAR previousSignAndOverflow;
|
---|
90 | UCHAR byte;
|
---|
91 |
|
---|
92 | UNREFERENCED_PARAMETER(Interrupt);
|
---|
93 |
|
---|
94 | I8xPrint((2, "I8042PRT-I8042MouseInterruptService: enter\n"));
|
---|
95 |
|
---|
96 | deviceObject = (PDEVICE_OBJECT) Context;
|
---|
97 | deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
|
---|
98 |
|
---|
99 | //
|
---|
100 | // Verify that this device really interrupted. Check the status
|
---|
101 | // register. The Output Buffer Full bit should be set, and the
|
---|
102 | // Auxiliary Device Output Buffer Full bit should be set.
|
---|
103 | //
|
---|
104 |
|
---|
105 | if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
|
---|
106 | & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
|
---|
107 | != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
|
---|
108 |
|
---|
109 | //
|
---|
110 | // Stall and then try again. The Olivetti MIPS machine
|
---|
111 | // sometimes gets a mouse interrupt before the status
|
---|
112 | // register is set.
|
---|
113 | //
|
---|
114 |
|
---|
115 | KeStallExecutionProcessor(10);
|
---|
116 | if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
|
---|
117 | & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
|
---|
118 | != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
|
---|
119 |
|
---|
120 | //
|
---|
121 | // Not our interrupt.
|
---|
122 | //
|
---|
123 |
|
---|
124 | I8xPrint((
|
---|
125 | 1,
|
---|
126 | "I8042PRT-I8042MouseInterruptService: not our interrupt!\n"
|
---|
127 | ));
|
---|
128 | return(FALSE);
|
---|
129 | }
|
---|
130 | }
|
---|
131 |
|
---|
132 | //
|
---|
133 | // Read the byte from the i8042 data port.
|
---|
134 | //
|
---|
135 |
|
---|
136 | I8xGetByteAsynchronous(
|
---|
137 | (CCHAR) MouseDeviceType,
|
---|
138 | deviceExtension,
|
---|
139 | &byte
|
---|
140 | );
|
---|
141 |
|
---|
142 | I8xPrint((
|
---|
143 | 3,
|
---|
144 | "I8042PRT-I8042MouseInterruptService: byte 0x%x\n",
|
---|
145 | byte
|
---|
146 | ));
|
---|
147 |
|
---|
148 | //
|
---|
149 | // Watch the data stream for a reset completion (0xaa) followed by the
|
---|
150 | // device id
|
---|
151 | //
|
---|
152 | // this pattern can appear as part of a normal data packet as well. This
|
---|
153 | // code assumes that sending an enable to an already enabled mouse will:
|
---|
154 | // * not hang the mouse
|
---|
155 | // * abort the current packet and return an ACK.
|
---|
156 | //
|
---|
157 |
|
---|
158 | if((deviceExtension->MouseExtension.LastByteReceived == 0xaa) &&
|
---|
159 | (byte == 0x00)) {
|
---|
160 |
|
---|
161 | PIO_ERROR_LOG_PACKET errorLogEntry;
|
---|
162 | UCHAR errorPacketSize;
|
---|
163 |
|
---|
164 | I8xPrint((
|
---|
165 | 1,
|
---|
166 | "I8042PRT-18042MouseInterruptService: reset detected in "
|
---|
167 | "data stream - current state is %d\n",
|
---|
168 | deviceExtension->MouseExtension.InputState
|
---|
169 | ));
|
---|
170 |
|
---|
171 | //
|
---|
172 | // Log a message/warning that the mouse has been reset - this should
|
---|
173 | // help us track down any wierd problems in the field
|
---|
174 | //
|
---|
175 |
|
---|
176 | errorPacketSize = sizeof(IO_ERROR_LOG_PACKET);
|
---|
177 |
|
---|
178 | errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(
|
---|
179 | deviceObject,
|
---|
180 | errorPacketSize
|
---|
181 | );
|
---|
182 |
|
---|
183 | if (errorLogEntry != NULL) {
|
---|
184 |
|
---|
185 | //
|
---|
186 | // If a reset occurred with the wheel mouse enabled make the message
|
---|
187 | // a warning and include the fact that the wheel is disabled in the
|
---|
188 | // message text
|
---|
189 | //
|
---|
190 |
|
---|
191 | if(deviceExtension->HardwarePresent & WHEELMOUSE_HARDWARE_PRESENT) {
|
---|
192 | errorLogEntry->ErrorCode = I8042_UNEXPECTED_WHEEL_MOUSE_RESET;
|
---|
193 | } else {
|
---|
194 | errorLogEntry->ErrorCode = I8042_UNEXPECTED_MOUSE_RESET;
|
---|
195 | }
|
---|
196 |
|
---|
197 | errorLogEntry->DumpDataSize = 0;
|
---|
198 | errorLogEntry->SequenceNumber = 0;
|
---|
199 | errorLogEntry->MajorFunctionCode = 0;
|
---|
200 | errorLogEntry->IoControlCode = 0;
|
---|
201 | errorLogEntry->RetryCount = 0;
|
---|
202 | errorLogEntry->UniqueErrorValue = 0xaa00;
|
---|
203 | errorLogEntry->FinalStatus = 0;
|
---|
204 |
|
---|
205 | IoWriteErrorLogEntry(errorLogEntry);
|
---|
206 | }
|
---|
207 |
|
---|
208 | deviceExtension->HardwarePresent &= ~WHEELMOUSE_HARDWARE_PRESENT;
|
---|
209 | deviceExtension->Configuration.MouseAttributes.NumberOfButtons = 2;
|
---|
210 |
|
---|
211 | //
|
---|
212 | // send the command to enable the mouse and wait for acknowledge.
|
---|
213 | //
|
---|
214 | // NOTE - this should be synchronized with the keyboard code
|
---|
215 | //
|
---|
216 |
|
---|
217 | I8xPutByteAsynchronous(
|
---|
218 | (CCHAR) CommandPort,
|
---|
219 | deviceExtension,
|
---|
220 | (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
|
---|
221 | );
|
---|
222 |
|
---|
223 | I8xPutByteAsynchronous(
|
---|
224 | (CCHAR) DataPort,
|
---|
225 | deviceExtension,
|
---|
226 | (UCHAR) ENABLE_MOUSE_TRANSMISSION
|
---|
227 | );
|
---|
228 |
|
---|
229 | //
|
---|
230 | // Set up state machine to look for acknowledgement.
|
---|
231 | //
|
---|
232 |
|
---|
233 | deviceExtension->MouseExtension.InputState = MouseExpectingACK;
|
---|
234 |
|
---|
235 | }
|
---|
236 |
|
---|
237 | deviceExtension->MouseExtension.LastByteReceived = byte;
|
---|
238 |
|
---|
239 | //
|
---|
240 | // Take the appropriate action, depending on the current state.
|
---|
241 | // When the state is Idle, we expect to receive mouse button
|
---|
242 | // data. When the state is XMovement, we expect to receive mouse
|
---|
243 | // motion in the X direction data. When the state is YMovement,
|
---|
244 | // we expect to receive mouse motion in the Y direction data. Once
|
---|
245 | // the Y motion data has been received, the data is queued to the
|
---|
246 | // mouse InputData queue, the mouse ISR DPC is requested, and the
|
---|
247 | // state returns to Idle.
|
---|
248 | //
|
---|
249 |
|
---|
250 | KeQueryTickCount(&newTick);
|
---|
251 | tickDelta.QuadPart =
|
---|
252 | newTick.QuadPart -
|
---|
253 | deviceExtension->MouseExtension.PreviousTick.QuadPart;
|
---|
254 |
|
---|
255 | if ((deviceExtension->MouseExtension.InputState != MouseIdle)
|
---|
256 | && (deviceExtension->MouseExtension.InputState != MouseExpectingACK)
|
---|
257 | && ((tickDelta.LowPart >= deviceExtension->MouseExtension.SynchTickCount)
|
---|
258 | || (tickDelta.HighPart != 0))) {
|
---|
259 |
|
---|
260 | //
|
---|
261 | // It has been a long time since we got a byte of
|
---|
262 | // the data packet. Assume that we are now receiving
|
---|
263 | // the first byte of a new packet, and discard any
|
---|
264 | // partially received packet.
|
---|
265 | //
|
---|
266 | // N.B. We assume that SynchTickCount is ULONG, and avoid
|
---|
267 | // a LARGE_INTEGER compare with tickDelta...
|
---|
268 | //
|
---|
269 |
|
---|
270 | I8xPrint((
|
---|
271 | 1,
|
---|
272 | "I8042PRT-I8042MouseInterruptService: State was %d, synching\n",
|
---|
273 | deviceExtension->MouseExtension.InputState
|
---|
274 | ));
|
---|
275 |
|
---|
276 | deviceExtension->MouseExtension.InputState = MouseIdle;
|
---|
277 | }
|
---|
278 |
|
---|
279 | deviceExtension->MouseExtension.PreviousTick = newTick;
|
---|
280 |
|
---|
281 | switch(deviceExtension->MouseExtension.InputState) {
|
---|
282 |
|
---|
283 | //
|
---|
284 | // The mouse interrupted with a status byte. The status byte
|
---|
285 | // contains information on the mouse button state along with
|
---|
286 | // the sign and overflow bits for the (yet-to-be-received)
|
---|
287 | // X and Y motion bytes.
|
---|
288 | //
|
---|
289 |
|
---|
290 | case MouseIdle: {
|
---|
291 |
|
---|
292 | I8xPrint((
|
---|
293 | 3,
|
---|
294 | "I8042PRT-I8042MouseInterruptService: mouse status byte\n"
|
---|
295 | ));
|
---|
296 |
|
---|
297 | //
|
---|
298 | // Update CurrentInput with button transition data.
|
---|
299 | // I.e., set a button up/down bit in the Buttons field if
|
---|
300 | // the state of a given button has changed since we
|
---|
301 | // received the last packet.
|
---|
302 | //
|
---|
303 |
|
---|
304 | previousButtons =
|
---|
305 | deviceExtension->MouseExtension.PreviousButtons;
|
---|
306 |
|
---|
307 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags = 0;
|
---|
308 | deviceExtension->MouseExtension.CurrentInput.ButtonData = 0;
|
---|
309 |
|
---|
310 | if ((!(previousButtons & LEFT_BUTTON_DOWN))
|
---|
311 | && (byte & LEFT_BUTTON_DOWN)) {
|
---|
312 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
313 | MOUSE_LEFT_BUTTON_DOWN;
|
---|
314 | } else
|
---|
315 | if ((previousButtons & LEFT_BUTTON_DOWN)
|
---|
316 | && !(byte & LEFT_BUTTON_DOWN)) {
|
---|
317 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
318 | MOUSE_LEFT_BUTTON_UP;
|
---|
319 | }
|
---|
320 | if ((!(previousButtons & RIGHT_BUTTON_DOWN))
|
---|
321 | && (byte & RIGHT_BUTTON_DOWN)) {
|
---|
322 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
323 | MOUSE_RIGHT_BUTTON_DOWN;
|
---|
324 | } else
|
---|
325 | if ((previousButtons & RIGHT_BUTTON_DOWN)
|
---|
326 | && !(byte & RIGHT_BUTTON_DOWN)) {
|
---|
327 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
328 | MOUSE_RIGHT_BUTTON_UP;
|
---|
329 | }
|
---|
330 | if ((!(previousButtons & MIDDLE_BUTTON_DOWN))
|
---|
331 | && (byte & MIDDLE_BUTTON_DOWN)) {
|
---|
332 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
333 | MOUSE_MIDDLE_BUTTON_DOWN;
|
---|
334 | } else
|
---|
335 | if ((previousButtons & MIDDLE_BUTTON_DOWN)
|
---|
336 | && !(byte & MIDDLE_BUTTON_DOWN)) {
|
---|
337 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |=
|
---|
338 | MOUSE_MIDDLE_BUTTON_UP;
|
---|
339 | }
|
---|
340 |
|
---|
341 | //
|
---|
342 | // Save the button state for comparison the next time around.
|
---|
343 | //
|
---|
344 |
|
---|
345 | deviceExtension->MouseExtension.PreviousButtons =
|
---|
346 | byte & (RIGHT_BUTTON_DOWN|MIDDLE_BUTTON_DOWN|LEFT_BUTTON_DOWN);
|
---|
347 |
|
---|
348 | //
|
---|
349 | // Save the sign and overflow information from the current byte.
|
---|
350 | //
|
---|
351 |
|
---|
352 | deviceExtension->MouseExtension.CurrentSignAndOverflow =
|
---|
353 | (UCHAR) (byte & MOUSE_SIGN_OVERFLOW_MASK);
|
---|
354 |
|
---|
355 | //
|
---|
356 | // Update to the next state.
|
---|
357 | //
|
---|
358 |
|
---|
359 | deviceExtension->MouseExtension.InputState = XMovement;
|
---|
360 |
|
---|
361 | break;
|
---|
362 | }
|
---|
363 |
|
---|
364 | //
|
---|
365 | // The mouse interrupted with the X motion byte. Apply
|
---|
366 | // the sign and overflow bits from the mouse status byte received
|
---|
367 | // previously. Attempt to correct for bogus changes in sign
|
---|
368 | // that occur with large, rapid mouse movements.
|
---|
369 | //
|
---|
370 |
|
---|
371 | case XMovement: {
|
---|
372 |
|
---|
373 | I8xPrint((
|
---|
374 | 3,
|
---|
375 | "I8042PRT-I8042MouseInterruptService: mouse LastX byte\n"
|
---|
376 | ));
|
---|
377 |
|
---|
378 | //
|
---|
379 | // Update CurrentInput with the X motion data.
|
---|
380 | //
|
---|
381 |
|
---|
382 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
383 | & X_OVERFLOW) {
|
---|
384 |
|
---|
385 | //
|
---|
386 | // Handle overflow in the X direction. If the previous
|
---|
387 | // mouse movement overflowed too, ensure that the current
|
---|
388 | // overflow is in the same direction (i.e., that the sign
|
---|
389 | // is the same as it was for the previous event). We do this
|
---|
390 | // to correct for hardware problems -- it should not be possible
|
---|
391 | // to overflow in one direction and then immediately overflow
|
---|
392 | // in the opposite direction.
|
---|
393 | //
|
---|
394 |
|
---|
395 | previousSignAndOverflow =
|
---|
396 | deviceExtension->MouseExtension.PreviousSignAndOverflow;
|
---|
397 | if (previousSignAndOverflow & X_OVERFLOW) {
|
---|
398 | if ((previousSignAndOverflow & X_DATA_SIGN) !=
|
---|
399 | (deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
400 | & X_DATA_SIGN)) {
|
---|
401 | deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
402 | ^= X_DATA_SIGN;
|
---|
403 | }
|
---|
404 | }
|
---|
405 |
|
---|
406 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
|
---|
407 | X_DATA_SIGN)
|
---|
408 | deviceExtension->MouseExtension.CurrentInput.LastX =
|
---|
409 | (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
|
---|
410 | else
|
---|
411 | deviceExtension->MouseExtension.CurrentInput.LastX =
|
---|
412 | (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
|
---|
413 |
|
---|
414 | } else {
|
---|
415 |
|
---|
416 | //
|
---|
417 | // No overflow. Just store the data, correcting for the
|
---|
418 | // sign if necessary.
|
---|
419 | //
|
---|
420 |
|
---|
421 | deviceExtension->MouseExtension.CurrentInput.LastX =
|
---|
422 | (ULONG) byte;
|
---|
423 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
|
---|
424 | X_DATA_SIGN)
|
---|
425 | deviceExtension->MouseExtension.CurrentInput.LastX |=
|
---|
426 | MOUSE_MAXIMUM_NEGATIVE_DELTA;
|
---|
427 | }
|
---|
428 |
|
---|
429 | //
|
---|
430 | // Update to the next state.
|
---|
431 | //
|
---|
432 |
|
---|
433 | deviceExtension->MouseExtension.InputState = YMovement;
|
---|
434 |
|
---|
435 | break;
|
---|
436 | }
|
---|
437 |
|
---|
438 | //
|
---|
439 | // The mouse interrupted with the Y motion byte. Apply
|
---|
440 | // the sign and overflow bits from the mouse status byte received
|
---|
441 | // previously. [Attempt to correct for bogus changes in sign
|
---|
442 | // that occur with large, rapid mouse movements.] Write the
|
---|
443 | // data to the mouse InputData queue, and queue the mouse ISR DPC
|
---|
444 | // to complete the interrupt processing.
|
---|
445 | //
|
---|
446 |
|
---|
447 | case YMovement: {
|
---|
448 |
|
---|
449 | I8xPrint((
|
---|
450 | 3,
|
---|
451 | "I8042PRT-I8042MouseInterruptService: mouse LastY byte\n"
|
---|
452 | ));
|
---|
453 |
|
---|
454 | //
|
---|
455 | // Update CurrentInput with the Y motion data.
|
---|
456 | //
|
---|
457 |
|
---|
458 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
459 | & Y_OVERFLOW) {
|
---|
460 |
|
---|
461 | //
|
---|
462 | // Handle overflow in the Y direction. If the previous
|
---|
463 | // mouse movement overflowed too, ensure that the current
|
---|
464 | // overflow is in the same direction (i.e., that the sign
|
---|
465 | // is the same as it was for the previous event). We do this
|
---|
466 | // to correct for hardware problems -- it should not be possible
|
---|
467 | // to overflow in one direction and then immediately overflow
|
---|
468 | // in the opposite direction.
|
---|
469 | //
|
---|
470 |
|
---|
471 | previousSignAndOverflow =
|
---|
472 | deviceExtension->MouseExtension.PreviousSignAndOverflow;
|
---|
473 | if (previousSignAndOverflow & Y_OVERFLOW) {
|
---|
474 | if ((previousSignAndOverflow & Y_DATA_SIGN) !=
|
---|
475 | (deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
476 | & Y_DATA_SIGN)) {
|
---|
477 | deviceExtension->MouseExtension.CurrentSignAndOverflow
|
---|
478 | ^= Y_DATA_SIGN;
|
---|
479 | }
|
---|
480 | }
|
---|
481 |
|
---|
482 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
|
---|
483 | Y_DATA_SIGN)
|
---|
484 | deviceExtension->MouseExtension.CurrentInput.LastY =
|
---|
485 | (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
|
---|
486 | else
|
---|
487 | deviceExtension->MouseExtension.CurrentInput.LastY =
|
---|
488 | (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
|
---|
489 |
|
---|
490 | } else {
|
---|
491 |
|
---|
492 | //
|
---|
493 | // No overflow. Just store the data, correcting for the
|
---|
494 | // sign if necessary.
|
---|
495 | //
|
---|
496 |
|
---|
497 | deviceExtension->MouseExtension.CurrentInput.LastY =
|
---|
498 | (ULONG) byte;
|
---|
499 | if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
|
---|
500 | Y_DATA_SIGN)
|
---|
501 | deviceExtension->MouseExtension.CurrentInput.LastY |=
|
---|
502 | MOUSE_MAXIMUM_NEGATIVE_DELTA;
|
---|
503 |
|
---|
504 | //
|
---|
505 | // Negate the LastY value (the hardware reports positive
|
---|
506 | // motion in the direction that we consider negative).
|
---|
507 | //
|
---|
508 |
|
---|
509 | deviceExtension->MouseExtension.CurrentInput.LastY =
|
---|
510 | -deviceExtension->MouseExtension.CurrentInput.LastY;
|
---|
511 |
|
---|
512 | }
|
---|
513 |
|
---|
514 | //
|
---|
515 | // Update our notion of the previous sign and overflow bits for
|
---|
516 | // the start of the next mouse input sequence.
|
---|
517 | //
|
---|
518 |
|
---|
519 | deviceExtension->MouseExtension.PreviousSignAndOverflow =
|
---|
520 | deviceExtension->MouseExtension.CurrentSignAndOverflow;
|
---|
521 |
|
---|
522 | //
|
---|
523 | // Choose the next state. The WheelMouse has an extra byte of data
|
---|
524 | // for us
|
---|
525 | //
|
---|
526 |
|
---|
527 | if(deviceExtension->HardwarePresent & WHEELMOUSE_HARDWARE_PRESENT) {
|
---|
528 |
|
---|
529 | deviceExtension->MouseExtension.InputState = ZMovement;
|
---|
530 |
|
---|
531 | } else {
|
---|
532 | // VBOX begin
|
---|
533 | // this field is sticky, so first reset it for original behavior
|
---|
534 | deviceExtension->MouseExtension.CurrentInput.Flags = MOUSE_MOVE_RELATIVE;
|
---|
535 |
|
---|
536 | { // open a new scope
|
---|
537 | VMMDevReqMouseStatus *req = deviceExtension->reqIS;
|
---|
538 |
|
---|
539 | if (req)
|
---|
540 | {
|
---|
541 | int rc = VbglGRPerform (&req->header);
|
---|
542 |
|
---|
543 | if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(req->header.rc))
|
---|
544 | {
|
---|
545 | if (req->mouseFeatures & VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE)
|
---|
546 | {
|
---|
547 | // make it an absolute move
|
---|
548 | deviceExtension->MouseExtension.CurrentInput.Flags = MOUSE_MOVE_ABSOLUTE;
|
---|
549 | deviceExtension->MouseExtension.CurrentInput.LastX = req->pointerXPos;
|
---|
550 | deviceExtension->MouseExtension.CurrentInput.LastY = req->pointerYPos;
|
---|
551 | }
|
---|
552 | }
|
---|
553 | else
|
---|
554 | {
|
---|
555 | dprintf(("i8042prt: ERROR querying mouse capabilities from VMMDev."
|
---|
556 | "rc = %Vrc, VMMDev rc = %Vrc\n", rc, req->header.rc));
|
---|
557 | }
|
---|
558 | }
|
---|
559 | } // close scope
|
---|
560 | // VBOX end
|
---|
561 | I8xQueueCurrentInput(deviceObject);
|
---|
562 | deviceExtension->MouseExtension.InputState = MouseIdle;
|
---|
563 |
|
---|
564 | }
|
---|
565 | break;
|
---|
566 | }
|
---|
567 |
|
---|
568 | case ZMovement: {
|
---|
569 |
|
---|
570 | I8xPrint((
|
---|
571 | 3,
|
---|
572 | "I8042PRT-I8042MouseInterruptService: mouse LastZ byte\n"
|
---|
573 | ));
|
---|
574 |
|
---|
575 | //
|
---|
576 | // Check to see if we got any z data
|
---|
577 | // If there were any changes in the button state, ignore the
|
---|
578 | // z data
|
---|
579 | //
|
---|
580 |
|
---|
581 | // if((byte)&&(deviceExtension->MouseExtension.CurrentInput.Buttons == 0)) {
|
---|
582 | if(byte) {
|
---|
583 |
|
---|
584 | //
|
---|
585 | // Sign extend the Z information and store it into the extra
|
---|
586 | // information field
|
---|
587 | //
|
---|
588 |
|
---|
589 | if(byte & 0x80) {
|
---|
590 | deviceExtension->MouseExtension.CurrentInput.ButtonData = 0x0078;
|
---|
591 | } else {
|
---|
592 | deviceExtension->MouseExtension.CurrentInput.ButtonData = 0xFF88;
|
---|
593 | }
|
---|
594 |
|
---|
595 | deviceExtension->MouseExtension.CurrentInput.ButtonFlags |= MOUSE_WHEEL;
|
---|
596 |
|
---|
597 | }
|
---|
598 | // VBOX begin
|
---|
599 | // this field is sticky, so first reset it for original behavior
|
---|
600 | deviceExtension->MouseExtension.CurrentInput.Flags = MOUSE_MOVE_RELATIVE;
|
---|
601 |
|
---|
602 | { // open a new scope
|
---|
603 | VMMDevReqMouseStatus *req = deviceExtension->reqIS;
|
---|
604 |
|
---|
605 | if (req)
|
---|
606 | {
|
---|
607 | int rc = VbglGRPerform (&req->header);
|
---|
608 |
|
---|
609 | if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(req->header.rc))
|
---|
610 | {
|
---|
611 | if (req->mouseFeatures & VBOXGUEST_MOUSE_HOST_CAN_ABSOLUTE)
|
---|
612 | {
|
---|
613 | // make it an absolute move
|
---|
614 | deviceExtension->MouseExtension.CurrentInput.Flags = MOUSE_MOVE_ABSOLUTE;
|
---|
615 | deviceExtension->MouseExtension.CurrentInput.LastX = req->pointerXPos;
|
---|
616 | deviceExtension->MouseExtension.CurrentInput.LastY = req->pointerYPos;
|
---|
617 | }
|
---|
618 | }
|
---|
619 | else
|
---|
620 | {
|
---|
621 | dprintf(("i8042prt: ERROR querying mouse capabilities from VMMDev."
|
---|
622 | "rc = %Vrc, VMMDev rc = %Vrc\n", rc, req->header.rc));
|
---|
623 | }
|
---|
624 | }
|
---|
625 | } // close scope
|
---|
626 | // VBOX end
|
---|
627 |
|
---|
628 | //
|
---|
629 | // Pack the data on to the class driver
|
---|
630 | //
|
---|
631 |
|
---|
632 | I8xQueueCurrentInput(deviceObject);
|
---|
633 |
|
---|
634 | //
|
---|
635 | // Reset the state
|
---|
636 | //
|
---|
637 |
|
---|
638 | deviceExtension->MouseExtension.InputState = MouseIdle;
|
---|
639 |
|
---|
640 | break;
|
---|
641 | }
|
---|
642 |
|
---|
643 | case MouseExpectingACK: {
|
---|
644 |
|
---|
645 | //
|
---|
646 | // This is a special case. We hit this on one of the very
|
---|
647 | // first mouse interrupts following the IoConnectInterrupt.
|
---|
648 | // The interrupt is caused when we enable mouse transmissions
|
---|
649 | // via I8xMouseEnableTransmission() -- the hardware returns
|
---|
650 | // an ACK. Just toss this byte away, and set the input state
|
---|
651 | // to coincide with the start of a new mouse data packet.
|
---|
652 | //
|
---|
653 |
|
---|
654 | I8xPrint((
|
---|
655 | 1,
|
---|
656 | "I8042PRT-I8042MouseInterruptService: expecting ACK (0x%x), got 0x%x\n",
|
---|
657 | (ULONG) ACKNOWLEDGE,
|
---|
658 | (ULONG) byte
|
---|
659 | ));
|
---|
660 |
|
---|
661 | if (byte == (UCHAR) ACKNOWLEDGE) {
|
---|
662 | deviceExtension->MouseExtension.InputState = MouseIdle;
|
---|
663 | } else if (byte == (UCHAR) RESEND) {
|
---|
664 |
|
---|
665 | //
|
---|
666 | // Resend the "Enable Mouse Transmission" sequence.
|
---|
667 | //
|
---|
668 | // NOTE: This is a hack for the Olivetti MIPS machine,
|
---|
669 | // which sends a resend response if a key is held down
|
---|
670 | // while we're attempting the I8xMouseEnableTransmission.
|
---|
671 | //
|
---|
672 |
|
---|
673 | I8xPutByteAsynchronous(
|
---|
674 | (CCHAR) CommandPort,
|
---|
675 | deviceExtension,
|
---|
676 | (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
|
---|
677 | );
|
---|
678 |
|
---|
679 | I8xPutByteAsynchronous(
|
---|
680 | (CCHAR) DataPort,
|
---|
681 | deviceExtension,
|
---|
682 | (UCHAR) ENABLE_MOUSE_TRANSMISSION
|
---|
683 | );
|
---|
684 | }
|
---|
685 |
|
---|
686 | break;
|
---|
687 | }
|
---|
688 |
|
---|
689 | default: {
|
---|
690 |
|
---|
691 | I8xPrint((
|
---|
692 | 3,
|
---|
693 | "I8042PRT-I8042MouseInterruptService: INVALID STATE\n"
|
---|
694 | ));
|
---|
695 |
|
---|
696 | //
|
---|
697 | // Queue a DPC to log an internal driver error.
|
---|
698 | //
|
---|
699 |
|
---|
700 | KeInsertQueueDpc(
|
---|
701 | &deviceExtension->ErrorLogDpc,
|
---|
702 | (PIRP) NULL,
|
---|
703 | (PVOID) (ULONG) I8042_INVALID_ISR_STATE
|
---|
704 | );
|
---|
705 |
|
---|
706 | ASSERT(FALSE);
|
---|
707 | break;
|
---|
708 | }
|
---|
709 |
|
---|
710 | }
|
---|
711 |
|
---|
712 | I8xPrint((2, "I8042PRT-I8042MouseInterruptService: exit\n"));
|
---|
713 |
|
---|
714 | return(TRUE);
|
---|
715 | }
|
---|
716 | |
---|
717 |
|
---|
718 | NTSTATUS
|
---|
719 | I8xQueryNumberOfMouseButtons(
|
---|
720 | IN PDEVICE_OBJECT DeviceObject,
|
---|
721 | OUT PUCHAR NumberOfMouseButtons
|
---|
722 | )
|
---|
723 |
|
---|
724 | /*++
|
---|
725 |
|
---|
726 | Routine Description:
|
---|
727 |
|
---|
728 | This implements logitech's method for detecting the number of
|
---|
729 | mouse buttons. If anything doesn't go as expected then 0
|
---|
730 | is returned.
|
---|
731 |
|
---|
732 | Calling this routine will set the mouse resolution to something
|
---|
733 | really low. The mouse resolution should be reset after this
|
---|
734 | call.
|
---|
735 |
|
---|
736 | Arguments:
|
---|
737 |
|
---|
738 | DeviceObject - Supplies the device object.
|
---|
739 |
|
---|
740 | NumberOfMouseButtons - Returns the number of mouse buttons or 0 if
|
---|
741 | the device did not support this type of
|
---|
742 | mouse button detection.
|
---|
743 |
|
---|
744 | Return Value:
|
---|
745 |
|
---|
746 | An NTSTATUS code indicating success or failure.
|
---|
747 |
|
---|
748 | --*/
|
---|
749 |
|
---|
750 | {
|
---|
751 | NTSTATUS status;
|
---|
752 | PDEVICE_EXTENSION deviceExtension;
|
---|
753 | ULONG i;
|
---|
754 | UCHAR byte, buttons;
|
---|
755 |
|
---|
756 | deviceExtension = DeviceObject->DeviceExtension;
|
---|
757 |
|
---|
758 | status = I8xPutBytePolled((CCHAR) DataPort, WAIT_FOR_ACKNOWLEDGE,
|
---|
759 | (CCHAR) MouseDeviceType, deviceExtension,
|
---|
760 | (UCHAR) SET_MOUSE_RESOLUTION);
|
---|
761 | if (!NT_SUCCESS(status)) {
|
---|
762 | return status;
|
---|
763 | }
|
---|
764 |
|
---|
765 | status = I8xPutBytePolled((CCHAR) DataPort, WAIT_FOR_ACKNOWLEDGE,
|
---|
766 | (CCHAR) MouseDeviceType, deviceExtension,
|
---|
767 | (UCHAR) 0x00);
|
---|
768 |
|
---|
769 | if (!NT_SUCCESS(status)) {
|
---|
770 | return status;
|
---|
771 | }
|
---|
772 |
|
---|
773 | for (i = 0; i < 3; i++) {
|
---|
774 |
|
---|
775 | status = I8xPutBytePolled((CCHAR) DataPort, WAIT_FOR_ACKNOWLEDGE,
|
---|
776 | (CCHAR) MouseDeviceType, deviceExtension,
|
---|
777 | (UCHAR) SET_MOUSE_SCALING_1TO1);
|
---|
778 |
|
---|
779 | if (!NT_SUCCESS(status)) {
|
---|
780 | return status;
|
---|
781 | }
|
---|
782 | }
|
---|
783 |
|
---|
784 | status = I8xPutBytePolled((CCHAR) DataPort, WAIT_FOR_ACKNOWLEDGE,
|
---|
785 | (CCHAR) MouseDeviceType, deviceExtension,
|
---|
786 | (UCHAR) READ_MOUSE_STATUS);
|
---|
787 |
|
---|
788 | if (!NT_SUCCESS(status)) {
|
---|
789 | return status;
|
---|
790 | }
|
---|
791 |
|
---|
792 | status = I8xGetBytePolled((CCHAR) ControllerDeviceType, deviceExtension,
|
---|
793 | &byte);
|
---|
794 |
|
---|
795 |
|
---|
796 | if (!NT_SUCCESS(status)) {
|
---|
797 | return status;
|
---|
798 | }
|
---|
799 |
|
---|
800 | status = I8xGetBytePolled((CCHAR) ControllerDeviceType, deviceExtension,
|
---|
801 | &buttons);
|
---|
802 |
|
---|
803 |
|
---|
804 | if (!NT_SUCCESS(status)) {
|
---|
805 | return status;
|
---|
806 | }
|
---|
807 |
|
---|
808 | status = I8xGetBytePolled((CCHAR) ControllerDeviceType, deviceExtension,
|
---|
809 | &byte);
|
---|
810 |
|
---|
811 |
|
---|
812 | if (!NT_SUCCESS(status)) {
|
---|
813 | return status;
|
---|
814 | }
|
---|
815 |
|
---|
816 | if (buttons == 2 || buttons == 3) {
|
---|
817 | *NumberOfMouseButtons = buttons;
|
---|
818 | } else {
|
---|
819 | *NumberOfMouseButtons = 0;
|
---|
820 | }
|
---|
821 |
|
---|
822 | return status;
|
---|
823 | }
|
---|
824 | |
---|
825 |
|
---|
826 | NTSTATUS
|
---|
827 | I8xInitializeMouse(
|
---|
828 | IN PDEVICE_OBJECT DeviceObject
|
---|
829 | )
|
---|
830 |
|
---|
831 | /*++
|
---|
832 |
|
---|
833 | Routine Description:
|
---|
834 |
|
---|
835 | This routine initializes the i8042 mouse hardware. It is called
|
---|
836 | only at initialization, and does not synchronize access to the hardware.
|
---|
837 |
|
---|
838 | Arguments:
|
---|
839 |
|
---|
840 | DeviceObject - Pointer to the device object.
|
---|
841 |
|
---|
842 | Return Value:
|
---|
843 |
|
---|
844 | Returns status.
|
---|
845 |
|
---|
846 | --*/
|
---|
847 |
|
---|
848 | {
|
---|
849 | NTSTATUS status;
|
---|
850 | PDEVICE_EXTENSION deviceExtension;
|
---|
851 | UCHAR byte;
|
---|
852 | ULONG i;
|
---|
853 | PIO_ERROR_LOG_PACKET errorLogEntry;
|
---|
854 | ULONG uniqueErrorValue;
|
---|
855 | NTSTATUS errorCode = STATUS_SUCCESS;
|
---|
856 | ULONG dumpCount = 0;
|
---|
857 | UCHAR numButtons;
|
---|
858 |
|
---|
859 | #define DUMP_COUNT 4
|
---|
860 | ULONG dumpData[DUMP_COUNT];
|
---|
861 |
|
---|
862 | I8xPrint((2, "I8042PRT-I8xInitializeMouse: enter\n"));
|
---|
863 |
|
---|
864 | for (i = 0; i < DUMP_COUNT; i++)
|
---|
865 | dumpData[i] = 0;
|
---|
866 |
|
---|
867 | //
|
---|
868 | // Get the device extension.
|
---|
869 | //
|
---|
870 |
|
---|
871 | deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
---|
872 |
|
---|
873 | //
|
---|
874 | // Reset the mouse. Send a Write To Auxiliary Device command to the
|
---|
875 | // 8042 controller. Then send the Reset Mouse command to the mouse
|
---|
876 | // through the 8042 data register. Expect to get back an ACK, followed
|
---|
877 | // by a completion code and the ID code (0x00).
|
---|
878 | //
|
---|
879 |
|
---|
880 | status = I8xPutBytePolled(
|
---|
881 | (CCHAR) DataPort,
|
---|
882 | WAIT_FOR_ACKNOWLEDGE,
|
---|
883 | (CCHAR) MouseDeviceType,
|
---|
884 | deviceExtension,
|
---|
885 | (UCHAR) MOUSE_RESET
|
---|
886 | );
|
---|
887 | if (!NT_SUCCESS(status)) {
|
---|
888 | I8xPrint((
|
---|
889 | 1,
|
---|
890 | "I8042PRT-I8xInitializeMouse: failed mouse reset, status 0x%x\n",
|
---|
891 | status
|
---|
892 | ));
|
---|
893 |
|
---|
894 | //
|
---|
895 | // Set up error log info.
|
---|
896 | //
|
---|
897 |
|
---|
898 | errorCode = I8042_MOU_RESET_COMMAND_FAILED;
|
---|
899 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 415;
|
---|
900 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
901 | dumpData[1] = DataPort;
|
---|
902 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
903 | dumpData[3] = MOUSE_RESET;
|
---|
904 | dumpCount = 4;
|
---|
905 |
|
---|
906 | goto I8xInitializeMouseExit;
|
---|
907 | }
|
---|
908 |
|
---|
909 | //
|
---|
910 | // Get the mouse reset responses. The first response should be a
|
---|
911 | // MOUSE_COMPLETE. The second response should be the mouse ID.
|
---|
912 | // Note that it is usually necessary to stall a long time to get the
|
---|
913 | // mouse reset/self-test to work. The stall value was determined by
|
---|
914 | // experimentation.
|
---|
915 | //
|
---|
916 | //
|
---|
917 |
|
---|
918 | for (i = 0; i < 11200; i++) {
|
---|
919 |
|
---|
920 | status = I8xGetBytePolled(
|
---|
921 | (CCHAR) ControllerDeviceType,
|
---|
922 | deviceExtension,
|
---|
923 | &byte
|
---|
924 | );
|
---|
925 |
|
---|
926 | if (NT_SUCCESS(status) && (byte == (UCHAR) MOUSE_COMPLETE)) {
|
---|
927 |
|
---|
928 | //
|
---|
929 | // The reset completed successfully.
|
---|
930 | //
|
---|
931 |
|
---|
932 | break;
|
---|
933 |
|
---|
934 |
|
---|
935 | } else {
|
---|
936 |
|
---|
937 | //
|
---|
938 | // Stall, and then try again to get a response from
|
---|
939 | // the reset.
|
---|
940 | //
|
---|
941 |
|
---|
942 | if (status == STATUS_IO_TIMEOUT) {
|
---|
943 |
|
---|
944 | //
|
---|
945 | // Stall, and then try again to get a response from
|
---|
946 | // the reset.
|
---|
947 | //
|
---|
948 |
|
---|
949 | KeStallExecutionProcessor(50);
|
---|
950 |
|
---|
951 | } else {
|
---|
952 |
|
---|
953 | break;
|
---|
954 |
|
---|
955 | }
|
---|
956 | }
|
---|
957 | }
|
---|
958 |
|
---|
959 | if (!NT_SUCCESS(status)) {
|
---|
960 | I8xPrint((
|
---|
961 | 1,
|
---|
962 | "I8042PRT-I8xInitializeMouse: failed reset response 1, status 0x%x, byte 0x%x\n",
|
---|
963 | status,
|
---|
964 | byte
|
---|
965 | ));
|
---|
966 |
|
---|
967 | //
|
---|
968 | // Set up error log info.
|
---|
969 | //
|
---|
970 |
|
---|
971 | errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
|
---|
972 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 420;
|
---|
973 | dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
|
---|
974 | dumpData[1] = ControllerDeviceType;
|
---|
975 | dumpData[2] = MOUSE_COMPLETE;
|
---|
976 | dumpData[3] = byte;
|
---|
977 | dumpCount = 4;
|
---|
978 |
|
---|
979 | goto I8xInitializeMouseExit;
|
---|
980 | }
|
---|
981 |
|
---|
982 | status = I8xGetBytePolled(
|
---|
983 | (CCHAR) ControllerDeviceType,
|
---|
984 | deviceExtension,
|
---|
985 | &byte
|
---|
986 | );
|
---|
987 |
|
---|
988 | if ((!NT_SUCCESS(status)) || (byte != MOUSE_ID_BYTE)) {
|
---|
989 | I8xPrint((
|
---|
990 | 1,
|
---|
991 | "I8042PRT-I8xInitializeMouse: failed reset response 2, status 0x%x, byte 0x%x\n",
|
---|
992 | status,
|
---|
993 | byte
|
---|
994 | ));
|
---|
995 |
|
---|
996 | //
|
---|
997 | // Set up error log info.
|
---|
998 | //
|
---|
999 |
|
---|
1000 | errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
|
---|
1001 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 425;
|
---|
1002 | dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
|
---|
1003 | dumpData[1] = ControllerDeviceType;
|
---|
1004 | dumpData[2] = MOUSE_ID_BYTE;
|
---|
1005 | dumpData[3] = byte;
|
---|
1006 | dumpCount = 4;
|
---|
1007 |
|
---|
1008 | goto I8xInitializeMouseExit;
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 | //
|
---|
1012 | // Check to see if this is a wheel mouse
|
---|
1013 | //
|
---|
1014 |
|
---|
1015 | I8xFindWheelMouse(DeviceObject);
|
---|
1016 |
|
---|
1017 | //
|
---|
1018 | // Try to detect the number of mouse buttons.
|
---|
1019 | //
|
---|
1020 |
|
---|
1021 | status = I8xQueryNumberOfMouseButtons(DeviceObject, &numButtons);
|
---|
1022 | if (!NT_SUCCESS(status)) {
|
---|
1023 | I8xPrint((
|
---|
1024 | 1,
|
---|
1025 | "I8042PRT-I8xInitializeMouse: failed to get buttons, status 0x%x\n",
|
---|
1026 | status
|
---|
1027 | ));
|
---|
1028 |
|
---|
1029 | //
|
---|
1030 | // Set up error log info.
|
---|
1031 | //
|
---|
1032 |
|
---|
1033 | errorCode = I8042_ERROR_DURING_BUTTONS_DETECT;
|
---|
1034 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 426;
|
---|
1035 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1036 | dumpData[1] = DataPort;
|
---|
1037 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1038 | dumpCount = 3;
|
---|
1039 |
|
---|
1040 | goto I8xInitializeMouseExit;
|
---|
1041 | } else if (numButtons) {
|
---|
1042 | deviceExtension->Configuration.MouseAttributes.NumberOfButtons =
|
---|
1043 | numButtons;
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 |
|
---|
1047 | //
|
---|
1048 | // Set mouse sampling rate. Send a Write To Auxiliary Device command
|
---|
1049 | // to the 8042 controller. Then send the Set Mouse Sampling Rate
|
---|
1050 | // command to the mouse through the 8042 data register,
|
---|
1051 | // followed by its parameter.
|
---|
1052 | //
|
---|
1053 |
|
---|
1054 | status = I8xPutBytePolled(
|
---|
1055 | (CCHAR) DataPort,
|
---|
1056 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1057 | (CCHAR) MouseDeviceType,
|
---|
1058 | deviceExtension,
|
---|
1059 | (UCHAR) SET_MOUSE_SAMPLING_RATE
|
---|
1060 | );
|
---|
1061 | if (!NT_SUCCESS(status)) {
|
---|
1062 | I8xPrint((
|
---|
1063 | 1,
|
---|
1064 | "I8042PRT-I8xInitializeMouse: failed write set sample rate, status 0x%x\n",
|
---|
1065 | status
|
---|
1066 | ));
|
---|
1067 |
|
---|
1068 | //
|
---|
1069 | // Set up error log info.
|
---|
1070 | //
|
---|
1071 |
|
---|
1072 | errorCode = I8042_SET_SAMPLE_RATE_FAILED;
|
---|
1073 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 435;
|
---|
1074 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1075 | dumpData[1] = DataPort;
|
---|
1076 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1077 | dumpData[3] = SET_MOUSE_SAMPLING_RATE;
|
---|
1078 | dumpCount = 4;
|
---|
1079 |
|
---|
1080 | goto I8xInitializeMouseExit;
|
---|
1081 | }
|
---|
1082 |
|
---|
1083 | status = I8xPutBytePolled(
|
---|
1084 | (CCHAR) DataPort,
|
---|
1085 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1086 | (CCHAR) MouseDeviceType,
|
---|
1087 | deviceExtension,
|
---|
1088 | (UCHAR) MOUSE_SAMPLE_RATE
|
---|
1089 | );
|
---|
1090 | if (!NT_SUCCESS(status)) {
|
---|
1091 | I8xPrint((
|
---|
1092 | 1,
|
---|
1093 | "I8042PRT-I8xInitializeMouse: failed write sample rate, status 0x%x\n",
|
---|
1094 | status
|
---|
1095 | ));
|
---|
1096 |
|
---|
1097 | //
|
---|
1098 | // Set up error log info.
|
---|
1099 | //
|
---|
1100 |
|
---|
1101 | errorCode = I8042_SET_SAMPLE_RATE_FAILED;
|
---|
1102 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 445;
|
---|
1103 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1104 | dumpData[1] = DataPort;
|
---|
1105 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1106 | dumpData[3] = MOUSE_SAMPLE_RATE;
|
---|
1107 | dumpCount = 4;
|
---|
1108 |
|
---|
1109 | goto I8xInitializeMouseExit;
|
---|
1110 | }
|
---|
1111 |
|
---|
1112 | //
|
---|
1113 | // Set the mouse resolution. Send a Write To Auxiliary Device command
|
---|
1114 | // to the 8042 controller. Then send the Set Mouse Resolution
|
---|
1115 | // command to the mouse through the 8042 data register,
|
---|
1116 | // followed by its parameter.
|
---|
1117 | //
|
---|
1118 |
|
---|
1119 | status = I8xPutBytePolled(
|
---|
1120 | (CCHAR) DataPort,
|
---|
1121 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1122 | (CCHAR) MouseDeviceType,
|
---|
1123 | deviceExtension,
|
---|
1124 | (UCHAR) SET_MOUSE_RESOLUTION
|
---|
1125 | );
|
---|
1126 | if (!NT_SUCCESS(status)) {
|
---|
1127 | I8xPrint((
|
---|
1128 | 1,
|
---|
1129 | "I8042PRT-I8xInitializeMouse: failed write set resolution, status 0x%x\n",
|
---|
1130 | status
|
---|
1131 | ));
|
---|
1132 |
|
---|
1133 | //
|
---|
1134 | // Set up error log info.
|
---|
1135 | //
|
---|
1136 |
|
---|
1137 | errorCode = I8042_SET_RESOLUTION_FAILED;
|
---|
1138 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 455;
|
---|
1139 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1140 | dumpData[1] = DataPort;
|
---|
1141 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1142 | dumpData[3] = SET_MOUSE_RESOLUTION;
|
---|
1143 | dumpCount = 4;
|
---|
1144 |
|
---|
1145 | goto I8xInitializeMouseExit;
|
---|
1146 | }
|
---|
1147 |
|
---|
1148 | status = I8xPutBytePolled(
|
---|
1149 | (CCHAR) DataPort,
|
---|
1150 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1151 | (CCHAR) MouseDeviceType,
|
---|
1152 | deviceExtension,
|
---|
1153 | (UCHAR) deviceExtension->Configuration.MouseResolution
|
---|
1154 | );
|
---|
1155 | if (!NT_SUCCESS(status)) {
|
---|
1156 | I8xPrint((
|
---|
1157 | 1,
|
---|
1158 | "I8042PRT-I8xInitializeMouse: failed set mouse resolution, status 0x%x\n",
|
---|
1159 | status
|
---|
1160 | ));
|
---|
1161 |
|
---|
1162 | //
|
---|
1163 | // Set up error log info.
|
---|
1164 | //
|
---|
1165 |
|
---|
1166 | errorCode = I8042_SET_RESOLUTION_FAILED;
|
---|
1167 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 465;
|
---|
1168 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1169 | dumpData[1] = DataPort;
|
---|
1170 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1171 | dumpData[3] = deviceExtension->Configuration.MouseResolution;
|
---|
1172 | dumpCount = 4;
|
---|
1173 |
|
---|
1174 | goto I8xInitializeMouseExit;
|
---|
1175 | }
|
---|
1176 |
|
---|
1177 | I8xInitializeMouseExit:
|
---|
1178 |
|
---|
1179 | if (!NT_SUCCESS(status)) {
|
---|
1180 |
|
---|
1181 | //
|
---|
1182 | // The mouse initialization failed. Log an error.
|
---|
1183 | //
|
---|
1184 |
|
---|
1185 | if (errorCode != STATUS_SUCCESS) {
|
---|
1186 | errorLogEntry = (PIO_ERROR_LOG_PACKET)
|
---|
1187 | IoAllocateErrorLogEntry(
|
---|
1188 | DeviceObject,
|
---|
1189 | (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
|
---|
1190 | + (dumpCount * sizeof(ULONG)))
|
---|
1191 | );
|
---|
1192 |
|
---|
1193 | if (errorLogEntry != NULL) {
|
---|
1194 |
|
---|
1195 | errorLogEntry->ErrorCode = errorCode;
|
---|
1196 | errorLogEntry->DumpDataSize = (USHORT) dumpCount * sizeof(ULONG);
|
---|
1197 | errorLogEntry->SequenceNumber = 0;
|
---|
1198 | errorLogEntry->MajorFunctionCode = 0;
|
---|
1199 | errorLogEntry->IoControlCode = 0;
|
---|
1200 | errorLogEntry->RetryCount = 0;
|
---|
1201 | errorLogEntry->UniqueErrorValue = uniqueErrorValue;
|
---|
1202 | errorLogEntry->FinalStatus = status;
|
---|
1203 | for (i = 0; i < dumpCount; i++)
|
---|
1204 | errorLogEntry->DumpData[i] = dumpData[i];
|
---|
1205 |
|
---|
1206 | IoWriteErrorLogEntry(errorLogEntry);
|
---|
1207 | }
|
---|
1208 | }
|
---|
1209 | }
|
---|
1210 |
|
---|
1211 | //
|
---|
1212 | // Initialize current mouse input packet state.
|
---|
1213 | //
|
---|
1214 |
|
---|
1215 | deviceExtension->MouseExtension.PreviousSignAndOverflow = 0;
|
---|
1216 | deviceExtension->MouseExtension.InputState = MouseExpectingACK;
|
---|
1217 | deviceExtension->MouseExtension.LastByteReceived = 0;
|
---|
1218 |
|
---|
1219 | I8xPrint((2, "I8042PRT-I8xInitializeMouse: exit\n"));
|
---|
1220 |
|
---|
1221 | return(status);
|
---|
1222 | }
|
---|
1223 | |
---|
1224 |
|
---|
1225 | VOID
|
---|
1226 | I8xMouseConfiguration(
|
---|
1227 | IN PINIT_EXTENSION InitializationData,
|
---|
1228 | IN PUNICODE_STRING RegistryPath,
|
---|
1229 | IN PUNICODE_STRING KeyboardDeviceName,
|
---|
1230 | IN PUNICODE_STRING PointerDeviceName
|
---|
1231 | )
|
---|
1232 |
|
---|
1233 | /*++
|
---|
1234 |
|
---|
1235 | Routine Description:
|
---|
1236 |
|
---|
1237 | This routine retrieves the configuration information for the mouse.
|
---|
1238 |
|
---|
1239 | Arguments:
|
---|
1240 |
|
---|
1241 | InitializationData - Pointer to the temporary device extension and some
|
---|
1242 | additional configuration information
|
---|
1243 |
|
---|
1244 | RegistryPath - Pointer to the null-terminated Unicode name of the
|
---|
1245 | registry path for this driver.
|
---|
1246 |
|
---|
1247 | KeyboardDeviceName - Pointer to the Unicode string that will receive
|
---|
1248 | the keyboard port device name.
|
---|
1249 |
|
---|
1250 | PointerDeviceName - Pointer to the Unicode string that will receive
|
---|
1251 | the pointer port device name.
|
---|
1252 |
|
---|
1253 |
|
---|
1254 | Return Value:
|
---|
1255 |
|
---|
1256 | None. As a side-effect, may set DeviceExtension->HardwarePresent.
|
---|
1257 |
|
---|
1258 | --*/
|
---|
1259 | {
|
---|
1260 | PDEVICE_EXTENSION deviceExtension = &(InitializationData->DeviceExtension);
|
---|
1261 | NTSTATUS status = STATUS_SUCCESS;
|
---|
1262 | INTERFACE_TYPE interfaceType;
|
---|
1263 | CONFIGURATION_TYPE controllerType = PointerController;
|
---|
1264 | CONFIGURATION_TYPE peripheralType = PointerPeripheral;
|
---|
1265 | ULONG i;
|
---|
1266 |
|
---|
1267 | for (i = 0; i < MaximumInterfaceType; i++) {
|
---|
1268 |
|
---|
1269 | //
|
---|
1270 | // Get the registry information for this device.
|
---|
1271 | //
|
---|
1272 |
|
---|
1273 | interfaceType = i;
|
---|
1274 | status = IoQueryDeviceDescription(&interfaceType,
|
---|
1275 | NULL,
|
---|
1276 | &controllerType,
|
---|
1277 | NULL,
|
---|
1278 | &peripheralType,
|
---|
1279 | NULL,
|
---|
1280 | I8xMousePeripheralCallout,
|
---|
1281 | (PVOID) InitializationData);
|
---|
1282 |
|
---|
1283 | if (InitializationData->DeviceExtension.HardwarePresent &
|
---|
1284 | MOUSE_HARDWARE_PRESENT) {
|
---|
1285 |
|
---|
1286 | //
|
---|
1287 | // If we didn't already get these when determining the keyboard
|
---|
1288 | // configuration, get the service parameters now (e.g.,
|
---|
1289 | // user-configurable number of resends, polling iterations, etc.).
|
---|
1290 | //
|
---|
1291 |
|
---|
1292 | if (!(InitializationData->DeviceExtension.HardwarePresent &
|
---|
1293 | KEYBOARD_HARDWARE_PRESENT))
|
---|
1294 | I8xServiceParameters(
|
---|
1295 | InitializationData,
|
---|
1296 | RegistryPath,
|
---|
1297 | KeyboardDeviceName,
|
---|
1298 | PointerDeviceName
|
---|
1299 | );
|
---|
1300 |
|
---|
1301 | //
|
---|
1302 | // Initialize mouse-specific configuration parameters.
|
---|
1303 | //
|
---|
1304 |
|
---|
1305 | InitializationData->DeviceExtension.Configuration.MouseAttributes.
|
---|
1306 | MouseIdentifier =
|
---|
1307 | MOUSE_I8042_HARDWARE;
|
---|
1308 |
|
---|
1309 | break;
|
---|
1310 |
|
---|
1311 | } else {
|
---|
1312 | I8xPrint((
|
---|
1313 | 1,
|
---|
1314 | "I8042PRT-I8xMouseConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
|
---|
1315 | interfaceType
|
---|
1316 | ));
|
---|
1317 | }
|
---|
1318 | }
|
---|
1319 | }
|
---|
1320 | |
---|
1321 |
|
---|
1322 | NTSTATUS
|
---|
1323 | I8xMouseEnableTransmission(
|
---|
1324 | IN PDEVICE_OBJECT DeviceObject
|
---|
1325 | )
|
---|
1326 |
|
---|
1327 | /*++
|
---|
1328 |
|
---|
1329 | Routine Description:
|
---|
1330 |
|
---|
1331 | This routine sends an Enable command to the mouse hardware, causing
|
---|
1332 | the mouse to begin transmissions. It is called at initialization
|
---|
1333 | time, but only after the interrupt has been connected. This is
|
---|
1334 | necessary so the driver can keep its notion of the mouse input data
|
---|
1335 | state in sync with the hardware (i.e., for this type of mouse there is no
|
---|
1336 | way to differentiate the first byte of a packet; if the user is randomly
|
---|
1337 | moving the mouse during boot/initialization, the first mouse interrupt we
|
---|
1338 | receive following IoConnectInterrupt could be for a byte that is not the
|
---|
1339 | start of a packet, and we have no way to know that).
|
---|
1340 |
|
---|
1341 | Arguments:
|
---|
1342 |
|
---|
1343 | DeviceObject - Pointer to the device object.
|
---|
1344 |
|
---|
1345 | Return Value:
|
---|
1346 |
|
---|
1347 | Returns status.
|
---|
1348 |
|
---|
1349 | --*/
|
---|
1350 |
|
---|
1351 | {
|
---|
1352 | NTSTATUS status;
|
---|
1353 | PDEVICE_EXTENSION deviceExtension;
|
---|
1354 | ULONG uniqueErrorValue;
|
---|
1355 | NTSTATUS errorCode = STATUS_SUCCESS;
|
---|
1356 | ULONG i;
|
---|
1357 | ULONG dumpCount = 0;
|
---|
1358 |
|
---|
1359 | #define DUMP_COUNT 4
|
---|
1360 | ULONG dumpData[DUMP_COUNT];
|
---|
1361 |
|
---|
1362 | I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: enter\n"));
|
---|
1363 |
|
---|
1364 | for (i = 0; i < DUMP_COUNT; i++)
|
---|
1365 | dumpData[i] = 0;
|
---|
1366 |
|
---|
1367 | //
|
---|
1368 | // Get the device extension.
|
---|
1369 | //
|
---|
1370 |
|
---|
1371 | deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
---|
1372 |
|
---|
1373 | //
|
---|
1374 | // Re-enable the mouse at the mouse hardware, so that it can transmit
|
---|
1375 | // data packets in continuous mode. Note that this is not the same
|
---|
1376 | // as enabling the mouse device at the 8042 controller. The mouse
|
---|
1377 | // hardware is sent an Enable command here, because it was
|
---|
1378 | // Disabled as a result of the mouse reset command performed
|
---|
1379 | // in I8xInitializeMouse().
|
---|
1380 | //
|
---|
1381 | // Note that we don't wait for an ACKNOWLEDGE back. The
|
---|
1382 | // ACKNOWLEDGE back will actually cause a mouse interrupt, which
|
---|
1383 | // then gets handled in the mouse ISR.
|
---|
1384 | //
|
---|
1385 |
|
---|
1386 | status = I8xPutBytePolled(
|
---|
1387 | (CCHAR) DataPort,
|
---|
1388 | NO_WAIT_FOR_ACKNOWLEDGE,
|
---|
1389 | (CCHAR) MouseDeviceType,
|
---|
1390 | deviceExtension,
|
---|
1391 | (UCHAR) ENABLE_MOUSE_TRANSMISSION
|
---|
1392 | );
|
---|
1393 | if (!NT_SUCCESS(status)) {
|
---|
1394 | I8xPrint((
|
---|
1395 | 1,
|
---|
1396 | "I8042PRT-I8xMouseEnableTransmission: failed write enable transmission, status 0x%x\n",
|
---|
1397 | status
|
---|
1398 | ));
|
---|
1399 |
|
---|
1400 | //
|
---|
1401 | // Set up error log info.
|
---|
1402 | //
|
---|
1403 |
|
---|
1404 | errorCode = I8042_MOU_ENABLE_XMIT;
|
---|
1405 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 475;
|
---|
1406 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1407 | dumpData[1] = DataPort;
|
---|
1408 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1409 | dumpData[3] = ENABLE_MOUSE_TRANSMISSION;
|
---|
1410 | dumpCount = 4;
|
---|
1411 |
|
---|
1412 | }
|
---|
1413 |
|
---|
1414 | I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: exit\n"));
|
---|
1415 |
|
---|
1416 | return(status);
|
---|
1417 | }
|
---|
1418 | |
---|
1419 |
|
---|
1420 | NTSTATUS
|
---|
1421 | I8xMousePeripheralCallout(
|
---|
1422 | IN PVOID Context,
|
---|
1423 | IN PUNICODE_STRING PathName,
|
---|
1424 | IN INTERFACE_TYPE BusType,
|
---|
1425 | IN ULONG BusNumber,
|
---|
1426 | IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
---|
1427 | IN CONFIGURATION_TYPE ControllerType,
|
---|
1428 | IN ULONG ControllerNumber,
|
---|
1429 | IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
---|
1430 | IN CONFIGURATION_TYPE PeripheralType,
|
---|
1431 | IN ULONG PeripheralNumber,
|
---|
1432 | IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
---|
1433 | )
|
---|
1434 |
|
---|
1435 | /*++
|
---|
1436 |
|
---|
1437 | Routine Description:
|
---|
1438 |
|
---|
1439 | This is the callout routine sent as a parameter to
|
---|
1440 | IoQueryDeviceDescription. It grabs the pointer controller and
|
---|
1441 | peripheral configuration information.
|
---|
1442 |
|
---|
1443 | Arguments:
|
---|
1444 |
|
---|
1445 | Context - Context parameter that was passed in by the routine
|
---|
1446 | that called IoQueryDeviceDescription.
|
---|
1447 |
|
---|
1448 | PathName - The full pathname for the registry key.
|
---|
1449 |
|
---|
1450 | BusType - Bus interface type (Isa, Eisa, Mca, etc.).
|
---|
1451 |
|
---|
1452 | BusNumber - The bus sub-key (0, 1, etc.).
|
---|
1453 |
|
---|
1454 | BusInformation - Pointer to the array of pointers to the full value
|
---|
1455 | information for the bus.
|
---|
1456 |
|
---|
1457 | ControllerType - The controller type (should be PointerController).
|
---|
1458 |
|
---|
1459 | ControllerNumber - The controller sub-key (0, 1, etc.).
|
---|
1460 |
|
---|
1461 | ControllerInformation - Pointer to the array of pointers to the full
|
---|
1462 | value information for the controller key.
|
---|
1463 |
|
---|
1464 | PeripheralType - The peripheral type (should be PointerPeripheral).
|
---|
1465 |
|
---|
1466 | PeripheralNumber - The peripheral sub-key.
|
---|
1467 |
|
---|
1468 | PeripheralInformation - Pointer to the array of pointers to the full
|
---|
1469 | value information for the peripheral key.
|
---|
1470 |
|
---|
1471 |
|
---|
1472 | Return Value:
|
---|
1473 |
|
---|
1474 | None. If successful, will have the following side-effects:
|
---|
1475 |
|
---|
1476 | - Sets DeviceObject->DeviceExtension->HardwarePresent.
|
---|
1477 | - Sets configuration fields in
|
---|
1478 | DeviceObject->DeviceExtension->Configuration.
|
---|
1479 |
|
---|
1480 | --*/
|
---|
1481 | {
|
---|
1482 | PDEVICE_EXTENSION deviceExtension;
|
---|
1483 | PINIT_EXTENSION initializationData;
|
---|
1484 | PI8042_CONFIGURATION_INFORMATION configuration;
|
---|
1485 | UNICODE_STRING unicodeIdentifier;
|
---|
1486 | ANSI_STRING ansiString;
|
---|
1487 | PUCHAR controllerData;
|
---|
1488 | NTSTATUS status = STATUS_SUCCESS;
|
---|
1489 | ULONG i;
|
---|
1490 | ULONG listCount;
|
---|
1491 | PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
|
---|
1492 | CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor;
|
---|
1493 | BOOLEAN portInfoNeeded;
|
---|
1494 | BOOLEAN defaultInterruptShare;
|
---|
1495 | KINTERRUPT_MODE defaultInterruptMode;
|
---|
1496 |
|
---|
1497 | I8xPrint((
|
---|
1498 | 1,
|
---|
1499 | "I8042PRT-I8xMousePeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
|
---|
1500 | PathName, BusType, BusNumber
|
---|
1501 | ));
|
---|
1502 | I8xPrint((
|
---|
1503 | 1,
|
---|
1504 | " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
|
---|
1505 | ControllerType, ControllerNumber, ControllerInformation
|
---|
1506 | ));
|
---|
1507 | I8xPrint((
|
---|
1508 | 1,
|
---|
1509 | " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
|
---|
1510 | PeripheralType, PeripheralNumber, PeripheralInformation
|
---|
1511 | ));
|
---|
1512 |
|
---|
1513 | //
|
---|
1514 | // Get the length of the peripheral identifier information.
|
---|
1515 | //
|
---|
1516 |
|
---|
1517 | unicodeIdentifier.Length = (USHORT)
|
---|
1518 | (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength;
|
---|
1519 |
|
---|
1520 | //
|
---|
1521 | // If we already have the configuration information for the
|
---|
1522 | // pointer peripheral, or if the peripheral identifier is missing,
|
---|
1523 | // just return.
|
---|
1524 | //
|
---|
1525 |
|
---|
1526 | initializationData = (PINIT_EXTENSION) Context;
|
---|
1527 | deviceExtension = &(initializationData->DeviceExtension);
|
---|
1528 |
|
---|
1529 | if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)
|
---|
1530 | || (unicodeIdentifier.Length == 0)) {
|
---|
1531 | return (status);
|
---|
1532 | }
|
---|
1533 |
|
---|
1534 | configuration = &deviceExtension->Configuration;
|
---|
1535 |
|
---|
1536 | //
|
---|
1537 | // Get the identifier information for the peripheral.
|
---|
1538 | //
|
---|
1539 |
|
---|
1540 | unicodeIdentifier.MaximumLength = unicodeIdentifier.Length;
|
---|
1541 | unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation +
|
---|
1542 | IoQueryDeviceIdentifier))) +
|
---|
1543 | (*(PeripheralInformation +
|
---|
1544 | IoQueryDeviceIdentifier))->DataOffset);
|
---|
1545 | I8xPrint((
|
---|
1546 | 1,
|
---|
1547 | "I8042PRT-I8xMousePeripheralCallout: Mouse type %ws\n",
|
---|
1548 | unicodeIdentifier.Buffer));
|
---|
1549 |
|
---|
1550 | //
|
---|
1551 | // Verify that this is an i8042 mouse.
|
---|
1552 | //
|
---|
1553 |
|
---|
1554 | status = RtlUnicodeStringToAnsiString(
|
---|
1555 | &ansiString,
|
---|
1556 | &unicodeIdentifier,
|
---|
1557 | TRUE
|
---|
1558 | );
|
---|
1559 |
|
---|
1560 | if (!NT_SUCCESS(status)) {
|
---|
1561 | I8xPrint((
|
---|
1562 | 1,
|
---|
1563 | "I8042PRT-I8xMousePeripheralCallout: Could not convert identifier to Ansi\n"
|
---|
1564 | ));
|
---|
1565 | return(status);
|
---|
1566 | }
|
---|
1567 |
|
---|
1568 | if (strstr(ansiString.Buffer, "PS2")) {
|
---|
1569 |
|
---|
1570 | //
|
---|
1571 | // There is a mouse on the i8042 controller.
|
---|
1572 | //
|
---|
1573 |
|
---|
1574 | deviceExtension->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
|
---|
1575 | }
|
---|
1576 |
|
---|
1577 | RtlFreeAnsiString(&ansiString);
|
---|
1578 |
|
---|
1579 | if (!(deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)) {
|
---|
1580 | return(status);
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | if (!(deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) {
|
---|
1584 |
|
---|
1585 | //
|
---|
1586 | // If we don't already have the bus information as the result
|
---|
1587 | // of the keyboard configuration, grab it now.
|
---|
1588 | //
|
---|
1589 |
|
---|
1590 | configuration->InterfaceType = BusType;
|
---|
1591 | configuration->BusNumber = BusNumber;
|
---|
1592 | configuration->FloatingSave = I8042_FLOATING_SAVE;
|
---|
1593 | }
|
---|
1594 |
|
---|
1595 | if (configuration->InterfaceType == MicroChannel) {
|
---|
1596 | defaultInterruptShare = TRUE;
|
---|
1597 | defaultInterruptMode = LevelSensitive;
|
---|
1598 | } else {
|
---|
1599 | defaultInterruptShare = I8042_INTERRUPT_SHARE;
|
---|
1600 | defaultInterruptMode = I8042_INTERRUPT_MODE;
|
---|
1601 | }
|
---|
1602 |
|
---|
1603 | //
|
---|
1604 | // Look through the controller's resource list for interrupt
|
---|
1605 | // and (possibly) port configuration information.
|
---|
1606 | //
|
---|
1607 |
|
---|
1608 | if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
|
---|
1609 | controllerData = ((PUCHAR) (*(ControllerInformation +
|
---|
1610 | IoQueryDeviceConfigurationData))) +
|
---|
1611 | (*(ControllerInformation +
|
---|
1612 | IoQueryDeviceConfigurationData))->DataOffset;
|
---|
1613 |
|
---|
1614 | controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
|
---|
1615 | PartialResourceList);
|
---|
1616 |
|
---|
1617 | listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
|
---|
1618 |
|
---|
1619 | resourceDescriptor =
|
---|
1620 | ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
|
---|
1621 |
|
---|
1622 | portInfoNeeded = configuration->PortListCount? FALSE:TRUE;
|
---|
1623 |
|
---|
1624 | for (i = 0; i < listCount; i++, resourceDescriptor++) {
|
---|
1625 | switch(resourceDescriptor->Type) {
|
---|
1626 | case CmResourceTypePort:
|
---|
1627 |
|
---|
1628 | if (portInfoNeeded) {
|
---|
1629 |
|
---|
1630 | //
|
---|
1631 | // If we don't already have the port information as
|
---|
1632 | // a result of the keyboard configuration, copy it
|
---|
1633 | // to the port list.
|
---|
1634 | //
|
---|
1635 |
|
---|
1636 | configuration->PortList[configuration->PortListCount] =
|
---|
1637 | *resourceDescriptor;
|
---|
1638 | configuration->PortList[configuration->PortListCount].ShareDisposition =
|
---|
1639 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
1640 | CmResourceShareDriverExclusive;
|
---|
1641 | configuration->PortListCount += 1;
|
---|
1642 |
|
---|
1643 | }
|
---|
1644 |
|
---|
1645 | break;
|
---|
1646 |
|
---|
1647 | case CmResourceTypeInterrupt:
|
---|
1648 |
|
---|
1649 | //
|
---|
1650 | // Copy the interrupt information.
|
---|
1651 | //
|
---|
1652 |
|
---|
1653 | configuration->MouseInterrupt = *resourceDescriptor;
|
---|
1654 | configuration->MouseInterrupt.ShareDisposition =
|
---|
1655 | defaultInterruptShare? CmResourceShareShared :
|
---|
1656 | CmResourceShareDeviceExclusive;
|
---|
1657 |
|
---|
1658 | break;
|
---|
1659 |
|
---|
1660 | default:
|
---|
1661 | break;
|
---|
1662 | }
|
---|
1663 | }
|
---|
1664 | }
|
---|
1665 |
|
---|
1666 | //
|
---|
1667 | // If no interrupt configuration information was found, use the
|
---|
1668 | // mouse driver defaults.
|
---|
1669 | //
|
---|
1670 |
|
---|
1671 | if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) {
|
---|
1672 |
|
---|
1673 | I8xPrint((
|
---|
1674 | 1,
|
---|
1675 | "I8042PRT-I8xMousePeripheralCallout: Using default mouse interrupt config\n"
|
---|
1676 | ));
|
---|
1677 |
|
---|
1678 | configuration->MouseInterrupt.Type = CmResourceTypeInterrupt;
|
---|
1679 | configuration->MouseInterrupt.ShareDisposition =
|
---|
1680 | defaultInterruptShare? CmResourceShareShared :
|
---|
1681 | CmResourceShareDeviceExclusive;
|
---|
1682 | configuration->MouseInterrupt.Flags =
|
---|
1683 | (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED :
|
---|
1684 | CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
---|
1685 | configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL;
|
---|
1686 | configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR;
|
---|
1687 | }
|
---|
1688 |
|
---|
1689 | I8xPrint((
|
---|
1690 | 1,
|
---|
1691 | "I8042PRT-I8xMousePeripheralCallout: Mouse interrupt config --\n"
|
---|
1692 | ));
|
---|
1693 | I8xPrint((
|
---|
1694 | 1,
|
---|
1695 | "%s, %s, Irq = %d\n",
|
---|
1696 | configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared?
|
---|
1697 | "Sharable" : "NonSharable",
|
---|
1698 | configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
|
---|
1699 | "Latched" : "Level Sensitive",
|
---|
1700 | configuration->MouseInterrupt.u.Interrupt.Vector
|
---|
1701 | ));
|
---|
1702 |
|
---|
1703 | //
|
---|
1704 | // If no port configuration information was found, use the
|
---|
1705 | // mouse driver defaults.
|
---|
1706 | //
|
---|
1707 |
|
---|
1708 | if (configuration->PortListCount == 0) {
|
---|
1709 |
|
---|
1710 | //
|
---|
1711 | // No port configuration information was found, so use
|
---|
1712 | // the driver defaults.
|
---|
1713 | //
|
---|
1714 |
|
---|
1715 | I8xPrint((
|
---|
1716 | 1,
|
---|
1717 | "I8042PRT-I8xMousePeripheralCallout: Using default port config\n"
|
---|
1718 | ));
|
---|
1719 |
|
---|
1720 | configuration->PortList[DataPort].Type = CmResourceTypePort;
|
---|
1721 | configuration->PortList[DataPort].Flags = I8042_PORT_TYPE;
|
---|
1722 | configuration->PortList[DataPort].ShareDisposition =
|
---|
1723 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
1724 | CmResourceShareDriverExclusive;
|
---|
1725 | configuration->PortList[DataPort].u.Port.Start.LowPart =
|
---|
1726 | I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET;
|
---|
1727 | configuration->PortList[DataPort].u.Port.Start.HighPart = 0;
|
---|
1728 | configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH;
|
---|
1729 |
|
---|
1730 | configuration->PortList[CommandPort].Type = CmResourceTypePort;
|
---|
1731 | configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE;
|
---|
1732 | configuration->PortList[CommandPort].ShareDisposition =
|
---|
1733 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
1734 | CmResourceShareDriverExclusive;
|
---|
1735 | configuration->PortList[CommandPort].u.Port.Start.LowPart =
|
---|
1736 | I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET;
|
---|
1737 | configuration->PortList[CommandPort].u.Port.Start.HighPart = 0;
|
---|
1738 | configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH;
|
---|
1739 |
|
---|
1740 | configuration->PortListCount = 2;
|
---|
1741 | } else if (configuration->PortListCount == 1) {
|
---|
1742 |
|
---|
1743 | //
|
---|
1744 | // Kludge for Jazz machines. Their ARC firmware neglects to
|
---|
1745 | // separate out the port addresses, so fix that up here.
|
---|
1746 | //
|
---|
1747 |
|
---|
1748 | configuration->PortList[CommandPort] = configuration->PortList[DataPort];
|
---|
1749 | configuration->PortList[CommandPort].u.Port.Start.LowPart +=
|
---|
1750 | I8042_COMMAND_REGISTER_OFFSET;
|
---|
1751 | configuration->PortListCount += 1;
|
---|
1752 | } else {
|
---|
1753 |
|
---|
1754 | //
|
---|
1755 | // Put the lowest port address range in the DataPort element of
|
---|
1756 | // the port list.
|
---|
1757 | //
|
---|
1758 |
|
---|
1759 | if (configuration->PortList[CommandPort].u.Port.Start.LowPart
|
---|
1760 | < configuration->PortList[DataPort].u.Port.Start.LowPart) {
|
---|
1761 | tmpResourceDescriptor = configuration->PortList[DataPort];
|
---|
1762 | configuration->PortList[DataPort] =
|
---|
1763 | configuration->PortList[CommandPort];
|
---|
1764 | configuration->PortList[CommandPort] = tmpResourceDescriptor;
|
---|
1765 | }
|
---|
1766 | }
|
---|
1767 |
|
---|
1768 | #ifdef PNP_IDENTIFY
|
---|
1769 | //
|
---|
1770 | // In any event we're going to use the pointer based on this data,
|
---|
1771 | // so make sure we can tell PNP that we've claimed it later on
|
---|
1772 | //
|
---|
1773 |
|
---|
1774 | initializationData->MouseConfig.InterfaceType = BusType;
|
---|
1775 | initializationData->MouseConfig.InterfaceNumber = BusNumber;
|
---|
1776 | initializationData->MouseConfig.ControllerType = ControllerType;
|
---|
1777 | initializationData->MouseConfig.ControllerNumber = ControllerNumber;
|
---|
1778 | initializationData->MouseConfig.PeripheralType = PeripheralType;
|
---|
1779 | initializationData->MouseConfig.PeripheralNumber = PeripheralNumber;
|
---|
1780 | #endif
|
---|
1781 |
|
---|
1782 | for (i = 0; i < configuration->PortListCount; i++) {
|
---|
1783 |
|
---|
1784 | I8xPrint((
|
---|
1785 | 1,
|
---|
1786 | " %s, Ports 0x%x - 0x%x\n",
|
---|
1787 | configuration->PortList[i].ShareDisposition
|
---|
1788 | == CmResourceShareShared? "Sharable" : "NonSharable",
|
---|
1789 | configuration->PortList[i].u.Port.Start.LowPart,
|
---|
1790 | configuration->PortList[i].u.Port.Start.LowPart +
|
---|
1791 | configuration->PortList[i].u.Port.Length - 1
|
---|
1792 | ));
|
---|
1793 | }
|
---|
1794 |
|
---|
1795 | return(status);
|
---|
1796 | }
|
---|
1797 |
|
---|
1798 | |
---|
1799 |
|
---|
1800 | NTSTATUS
|
---|
1801 | I8xFindWheelMouse(
|
---|
1802 | IN PDEVICE_OBJECT DeviceObject
|
---|
1803 | )
|
---|
1804 |
|
---|
1805 | /*++
|
---|
1806 |
|
---|
1807 | Routine Description:
|
---|
1808 |
|
---|
1809 | This routine determines if the mouse is a Zoom mouse. The method
|
---|
1810 | of detection is to set the sample rate to 200Hz, then 100Hz, then 80Hz
|
---|
1811 | and then read the device ID. An ID of 3 indicates a zoom mouse.
|
---|
1812 |
|
---|
1813 | If the registry entry "EnableWheelDetection" is false then this
|
---|
1814 | routine will just return STATUS_NO_SUCH_DEVICE.
|
---|
1815 |
|
---|
1816 | Arguments:
|
---|
1817 |
|
---|
1818 | DeviceObject - Pointer to the device object
|
---|
1819 |
|
---|
1820 | Return Value:
|
---|
1821 |
|
---|
1822 | Returns status
|
---|
1823 |
|
---|
1824 | Remarks:
|
---|
1825 |
|
---|
1826 | As a side effect the sample rate is left at 80Hz and if a wheelmouse is
|
---|
1827 | attached it is in the wheel mode where packets are different.
|
---|
1828 |
|
---|
1829 | --*/
|
---|
1830 |
|
---|
1831 | {
|
---|
1832 | NTSTATUS status;
|
---|
1833 | PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
---|
1834 | UCHAR byte;
|
---|
1835 | ULONG i;
|
---|
1836 | PIO_ERROR_LOG_PACKET errorLogEntry;
|
---|
1837 | ULONG uniqueErrorValue = I8042_ERROR_VALUE_BASE + 480;
|
---|
1838 | NTSTATUS errorCode = STATUS_SUCCESS;
|
---|
1839 | ULONG dumpCount = 0;
|
---|
1840 | #define DUMP_COUNT 4
|
---|
1841 | ULONG dumpData[DUMP_COUNT];
|
---|
1842 | UCHAR ucCommands[] = {SET_MOUSE_SAMPLING_RATE, 200,
|
---|
1843 | SET_MOUSE_SAMPLING_RATE, 100,
|
---|
1844 | SET_MOUSE_SAMPLING_RATE, 80,
|
---|
1845 | GET_DEVICE_ID, 0 // NULL terminate
|
---|
1846 | };
|
---|
1847 | UCHAR commandCount = 0;
|
---|
1848 |
|
---|
1849 | I8xPrint((1, "I8042PRT-I8xFindWheelMouse: enter\n"));
|
---|
1850 |
|
---|
1851 | if(!deviceExtension->Configuration.EnableWheelDetection) {
|
---|
1852 |
|
---|
1853 | I8xPrint((1,
|
---|
1854 | "I8042PRT-I8xFindWheelMouse: Detection disabled in registry\n"
|
---|
1855 | ));
|
---|
1856 | return STATUS_NO_SUCH_DEVICE;
|
---|
1857 | }
|
---|
1858 |
|
---|
1859 | for(i = 0; i < DUMP_COUNT; i++)
|
---|
1860 | dumpData[i] = 0;
|
---|
1861 |
|
---|
1862 | KeStallExecutionProcessor(50);
|
---|
1863 |
|
---|
1864 | while(ucCommands[commandCount] != 0) {
|
---|
1865 |
|
---|
1866 | status = I8xPutBytePolled(
|
---|
1867 | (CCHAR) DataPort,
|
---|
1868 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1869 | (CCHAR) MouseDeviceType,
|
---|
1870 | deviceExtension,
|
---|
1871 | ucCommands[commandCount]
|
---|
1872 | );
|
---|
1873 |
|
---|
1874 | if(!NT_SUCCESS(status)) {
|
---|
1875 |
|
---|
1876 | I8xPrint((
|
---|
1877 | 1,
|
---|
1878 | "I8042PRT-I8xFindWheelMouse: failed write set sample rate, status 0x%x\n",
|
---|
1879 | status
|
---|
1880 | ));
|
---|
1881 |
|
---|
1882 | //
|
---|
1883 | // Set up error log info
|
---|
1884 | //
|
---|
1885 |
|
---|
1886 | errorCode = I8042_SET_SAMPLE_RATE_FAILED;
|
---|
1887 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1888 | dumpData[1] = DataPort;
|
---|
1889 | dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
|
---|
1890 | dumpData[3] = ucCommands[commandCount];
|
---|
1891 | dumpCount = 4;
|
---|
1892 |
|
---|
1893 | goto I8xFindWheelMouseExit;
|
---|
1894 | }
|
---|
1895 |
|
---|
1896 | commandCount++;
|
---|
1897 | uniqueErrorValue += 5;
|
---|
1898 | KeStallExecutionProcessor(50);
|
---|
1899 |
|
---|
1900 | }
|
---|
1901 |
|
---|
1902 | //
|
---|
1903 | // Get the mouse ID
|
---|
1904 | //
|
---|
1905 |
|
---|
1906 | for(i = 0; i < 5; i++) {
|
---|
1907 |
|
---|
1908 | status = I8xGetBytePolled(
|
---|
1909 | (CCHAR) ControllerDeviceType,
|
---|
1910 | deviceExtension,
|
---|
1911 | &byte
|
---|
1912 | );
|
---|
1913 |
|
---|
1914 | if(NT_SUCCESS(status)) {
|
---|
1915 |
|
---|
1916 | //
|
---|
1917 | // Read was successful - the ID has been returned
|
---|
1918 |
|
---|
1919 | break;
|
---|
1920 |
|
---|
1921 | }
|
---|
1922 |
|
---|
1923 | //
|
---|
1924 | // If the read timed out, stall and retry.
|
---|
1925 | // If some other error occured handle it outside the loop
|
---|
1926 | //
|
---|
1927 |
|
---|
1928 | if(status == STATUS_IO_TIMEOUT) {
|
---|
1929 |
|
---|
1930 | KeStallExecutionProcessor(50);
|
---|
1931 |
|
---|
1932 | } else {
|
---|
1933 |
|
---|
1934 | break;
|
---|
1935 |
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | }
|
---|
1939 |
|
---|
1940 | if((!NT_SUCCESS(status)) ||
|
---|
1941 | ((byte != MOUSE_ID_BYTE) && (byte != WHEELMOUSE_ID_BYTE))) {
|
---|
1942 |
|
---|
1943 | I8xPrint((
|
---|
1944 | 1,
|
---|
1945 | "I8042PRT-I8xFindWheelMouse: failed ID, status 0x%x, byte 0x%x\n",
|
---|
1946 | status,
|
---|
1947 | byte
|
---|
1948 | ));
|
---|
1949 |
|
---|
1950 | //
|
---|
1951 | // Set up error log info
|
---|
1952 | //
|
---|
1953 |
|
---|
1954 | errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
|
---|
1955 | dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
|
---|
1956 | dumpData[1] = ControllerDeviceType;
|
---|
1957 | dumpData[2] = MOUSE_ID_BYTE;
|
---|
1958 | dumpData[3] = byte;
|
---|
1959 | dumpCount = 4;
|
---|
1960 |
|
---|
1961 | goto I8xFindWheelMouseExit;
|
---|
1962 |
|
---|
1963 | } else if( byte == WHEELMOUSE_ID_BYTE) {
|
---|
1964 |
|
---|
1965 | //
|
---|
1966 | // Update the HardwarePresent to show a Z mouse is operational,
|
---|
1967 | // and set the appropriate mouse type flags
|
---|
1968 | //
|
---|
1969 |
|
---|
1970 | deviceExtension->HardwarePresent |=
|
---|
1971 | (WHEELMOUSE_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT);
|
---|
1972 |
|
---|
1973 | // deviceExtension->MouseExtension.MsData.MouseType |=
|
---|
1974 | // (DT_Z_MOUSE | DT_MOUSE);
|
---|
1975 |
|
---|
1976 | deviceExtension->Configuration.MouseAttributes.MouseIdentifier =
|
---|
1977 | WHEELMOUSE_I8042_HARDWARE;
|
---|
1978 |
|
---|
1979 | I8xPrint((
|
---|
1980 | 1,
|
---|
1981 | "I8042PRT-I8xFindWheelMouse: wheel mouse attached - running in wheel mode.\n"
|
---|
1982 | ));
|
---|
1983 | } else {
|
---|
1984 | deviceExtension->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
|
---|
1985 |
|
---|
1986 | I8xPrint((
|
---|
1987 | 1,
|
---|
1988 | "I8042PRT-I8xFindWheelMouse: Mouse attached - running in mouse mode.\n"
|
---|
1989 | ));
|
---|
1990 | }
|
---|
1991 |
|
---|
1992 | I8xFindWheelMouseExit:
|
---|
1993 |
|
---|
1994 | if (!NT_SUCCESS(status)) {
|
---|
1995 |
|
---|
1996 | //
|
---|
1997 | // The mouse initialization failed. Log an error.
|
---|
1998 | //
|
---|
1999 |
|
---|
2000 | if(errorCode != STATUS_SUCCESS) {
|
---|
2001 | errorLogEntry = (PIO_ERROR_LOG_PACKET)
|
---|
2002 | IoAllocateErrorLogEntry(
|
---|
2003 | DeviceObject,
|
---|
2004 | (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) +
|
---|
2005 | (dumpCount * sizeof(ULONG)))
|
---|
2006 | );
|
---|
2007 |
|
---|
2008 | if(errorLogEntry != NULL) {
|
---|
2009 |
|
---|
2010 | errorLogEntry->ErrorCode = errorCode;
|
---|
2011 | errorLogEntry->DumpDataSize = (USHORT) dumpCount * sizeof(ULONG);
|
---|
2012 | errorLogEntry->SequenceNumber = 0;
|
---|
2013 | errorLogEntry->MajorFunctionCode = 0;
|
---|
2014 | errorLogEntry->IoControlCode = 0;
|
---|
2015 | errorLogEntry->RetryCount = 0;
|
---|
2016 | errorLogEntry->UniqueErrorValue = uniqueErrorValue;
|
---|
2017 | errorLogEntry->FinalStatus = status;
|
---|
2018 | for(i = 0; i < dumpCount; i++) {
|
---|
2019 | errorLogEntry->DumpData[i] = dumpData[i];
|
---|
2020 | }
|
---|
2021 |
|
---|
2022 | IoWriteErrorLogEntry(errorLogEntry);
|
---|
2023 | }
|
---|
2024 | }
|
---|
2025 | }
|
---|
2026 |
|
---|
2027 | //
|
---|
2028 | // Initialize current mouse input packet state
|
---|
2029 | //
|
---|
2030 |
|
---|
2031 | deviceExtension->MouseExtension.PreviousSignAndOverflow = 0;
|
---|
2032 | deviceExtension->MouseExtension.InputState = MouseExpectingACK;
|
---|
2033 |
|
---|
2034 | I8xPrint((2, "I8042PRT-I8xFindWheelMouse: exit\n"));
|
---|
2035 |
|
---|
2036 | return status;
|
---|
2037 | }
|
---|
2038 |
|
---|
2039 | |
---|
2040 |
|
---|
2041 | VOID
|
---|
2042 | I8xQueueCurrentInput(
|
---|
2043 | IN PDEVICE_OBJECT DeviceObject
|
---|
2044 | )
|
---|
2045 |
|
---|
2046 | /*++
|
---|
2047 |
|
---|
2048 | Routine Description:
|
---|
2049 |
|
---|
2050 | This routine queues the current input data to be processed by a
|
---|
2051 | DPC outside the ISR
|
---|
2052 |
|
---|
2053 | Arguments:
|
---|
2054 |
|
---|
2055 | DeviceObject - Pointer to the device object
|
---|
2056 |
|
---|
2057 | Return Value:
|
---|
2058 |
|
---|
2059 | None
|
---|
2060 |
|
---|
2061 | --*/
|
---|
2062 |
|
---|
2063 | {
|
---|
2064 |
|
---|
2065 | PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
---|
2066 | #if 0 /* bird: unused */
|
---|
2067 | UCHAR buttonsDelta;
|
---|
2068 | UCHAR previousButtons;
|
---|
2069 | #endif
|
---|
2070 |
|
---|
2071 | //
|
---|
2072 | // If the mouse is enabled, add the data to the InputData queue
|
---|
2073 | // and queue the ISR DPC. One might wonder why we bother to
|
---|
2074 | // do all this processing of the mouse packet, only to toss it
|
---|
2075 | // away (i.e., not queue it) at this point. The answer is that
|
---|
2076 | // this mouse provides no data to allow the driver to determine
|
---|
2077 | // when the first byte of a packet is received -- if the driver
|
---|
2078 | // doesn't process all interrupts from the start, there is no
|
---|
2079 | // way to keep MouseExtension.InputState in synch with hardware
|
---|
2080 | // reality.
|
---|
2081 | //
|
---|
2082 |
|
---|
2083 | if (deviceExtension->MouseEnableCount) {
|
---|
2084 | deviceExtension->MouseExtension.CurrentInput.UnitId = deviceExtension->MouseExtension.UnitId;
|
---|
2085 |
|
---|
2086 | if (!I8xWriteDataToMouseQueue(
|
---|
2087 | &deviceExtension->MouseExtension,
|
---|
2088 | &deviceExtension->MouseExtension.CurrentInput
|
---|
2089 | )) {
|
---|
2090 |
|
---|
2091 | //
|
---|
2092 | // InputData queue overflowed.
|
---|
2093 | //
|
---|
2094 | // Queue a DPC to log an overrun error.
|
---|
2095 | //
|
---|
2096 |
|
---|
2097 | I8xPrint((
|
---|
2098 | 1,
|
---|
2099 | "I8042PRT-I8042MouseInterruptService: queue overflow\n"
|
---|
2100 | ));
|
---|
2101 |
|
---|
2102 | if (deviceExtension->MouseExtension.OkayToLogOverflow) {
|
---|
2103 | KeInsertQueueDpc(
|
---|
2104 | &deviceExtension->ErrorLogDpc,
|
---|
2105 | (PIRP) NULL,
|
---|
2106 | (PVOID) (ULONG) I8042_MOU_BUFFER_OVERFLOW
|
---|
2107 | );
|
---|
2108 | deviceExtension->MouseExtension.OkayToLogOverflow =
|
---|
2109 | FALSE;
|
---|
2110 | }
|
---|
2111 |
|
---|
2112 | } else if (deviceExtension->DpcInterlockMouse >= 0) {
|
---|
2113 |
|
---|
2114 | //
|
---|
2115 | // The ISR DPC is already executing. Tell the ISR DPC it has
|
---|
2116 | // more work to do by incrementing DpcInterlockMouse.
|
---|
2117 | //
|
---|
2118 |
|
---|
2119 | deviceExtension->DpcInterlockMouse += 1;
|
---|
2120 |
|
---|
2121 | } else {
|
---|
2122 |
|
---|
2123 | //
|
---|
2124 | // Queue the ISR DPC.
|
---|
2125 | //
|
---|
2126 |
|
---|
2127 | KeInsertQueueDpc(
|
---|
2128 | &deviceExtension->MouseIsrDpc,
|
---|
2129 | DeviceObject->CurrentIrp,
|
---|
2130 | NULL
|
---|
2131 | );
|
---|
2132 | }
|
---|
2133 |
|
---|
2134 | }
|
---|
2135 |
|
---|
2136 | return;
|
---|
2137 | }
|
---|
2138 |
|
---|