|
|
1.1 root 1: #if defined(i386)
2:
3: /*++
4:
5: Copyright (c) 1989, 1990, 1991, 1992, 1993 Microsoft Corporation
6:
7: Module Name:
8:
9: inpcmn.c
10:
11: Abstract:
12:
13: The common portions of the Microsoft InPort mouse port driver.
14: This file should not require modification to support new mice
15: that are similar to the InPort mouse.
16:
17: Environment:
18:
19: Kernel mode only.
20:
21: Notes:
22:
23: NOTES: (Future/outstanding issues)
24:
25: - Powerfail not implemented.
26:
27: - IOCTL_INTERNAL_MOUSE_DISCONNECT has not been implemented. It's not
28: needed until the class unload routine is implemented. Right now,
29: we don't want to allow the mouse class driver to unload.
30:
31: - Consolidate duplicate code, where possible and appropriate.
32:
33: Revision History:
34:
35: --*/
36:
37: #include "stdarg.h"
38: #include "stdio.h"
39: #include "string.h"
40: #include "ntddk.h"
41: #include "inport.h"
42: #include "inplog.h"
43:
44: //
45: // Declare the global debug flag for this driver.
46: //
47:
48: #if DBG
49: ULONG InportDebug = 0;
50: #endif
51:
52:
53: VOID
54: InportErrorLogDpc(
55: IN PKDPC Dpc,
56: IN PDEVICE_OBJECT DeviceObject,
57: IN PIRP Irp,
58: IN PVOID Context
59: )
60:
61: /*++
62:
63: Routine Description:
64:
65: This routine runs at DISPATCH_LEVEL IRQL to log errors that are
66: discovered at IRQL > DISPATCH_LEVEL (e.g., in the ISR routine or
67: in a routine that is executed via KeSynchronizeExecution). There
68: is not necessarily a current request associated with this condition.
69:
70: Arguments:
71:
72: Dpc - Pointer to the DPC object.
73:
74: DeviceObject - Pointer to the device object.
75:
76: Irp - Not used.
77:
78: Context - Indicates type of error to log.
79:
80: Return Value:
81:
82: None.
83:
84: --*/
85:
86: {
87: PDEVICE_EXTENSION deviceExtension;
88: PIO_ERROR_LOG_PACKET errorLogEntry;
89:
90: UNREFERENCED_PARAMETER(Dpc);
91: UNREFERENCED_PARAMETER(Irp);
92:
93: InpPrint((2, "INPORT-InportErrorLogDpc: enter\n"));
94:
95: deviceExtension = DeviceObject->DeviceExtension;
96:
97: //
98: // Log an error packet.
99: //
100:
101: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
102: DeviceObject,
103: sizeof(IO_ERROR_LOG_PACKET)
104: + (2 * sizeof(ULONG))
105: );
106: if (errorLogEntry != NULL) {
107:
108: errorLogEntry->DumpDataSize = 2 * sizeof(ULONG);
109:
110: if ((ULONG) Context == INPORT_MOU_BUFFER_OVERFLOW) {
111: errorLogEntry->UniqueErrorValue = INPORT_ERROR_VALUE_BASE + 210;
112: errorLogEntry->DumpData[0] = sizeof(MOUSE_INPUT_DATA);
113: errorLogEntry->DumpData[1] =
114: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
115: } else {
116: errorLogEntry->UniqueErrorValue = INPORT_ERROR_VALUE_BASE + 220;
117: errorLogEntry->DumpData[0] = 0;
118: errorLogEntry->DumpData[1] = 0;
119: }
120:
121: errorLogEntry->ErrorCode = (ULONG) Context;
122: errorLogEntry->SequenceNumber = 0;
123: errorLogEntry->MajorFunctionCode = 0;
124: errorLogEntry->IoControlCode = 0;
125: errorLogEntry->RetryCount = 0;
126: errorLogEntry->FinalStatus = 0;
127:
128: IoWriteErrorLogEntry(errorLogEntry);
129: }
130:
131: InpPrint((2, "INPORT-InportErrorLogDpc: exit\n"));
132:
133: }
134:
135: NTSTATUS
136: InportFlush(
137: IN PDEVICE_OBJECT DeviceObject,
138: IN PIRP Irp
139: )
140: {
141: UNREFERENCED_PARAMETER(DeviceObject);
142: UNREFERENCED_PARAMETER(Irp);
143:
144: InpPrint((2,"INPORT-InportFlush: enter\n"));
145: InpPrint((2,"INPORT-InportFlush: exit\n"));
146:
147: return(STATUS_NOT_IMPLEMENTED);
148: }
149:
150: NTSTATUS
151: InportInternalDeviceControl(
152: IN PDEVICE_OBJECT DeviceObject,
153: IN PIRP Irp
154: )
155:
156: /*++
157:
158: Routine Description:
159:
160: This routine is the dispatch routine for internal device control requests.
161:
162: Arguments:
163:
164: DeviceObject - Pointer to the device object.
165:
166: Irp - Pointer to the request packet.
167:
168: Return Value:
169:
170: Status is returned.
171:
172: --*/
173:
174: {
175:
176: PIO_STACK_LOCATION irpSp;
177: PDEVICE_EXTENSION deviceExtension;
178: NTSTATUS status;
179:
180: InpPrint((2,"INPORT-InportInternalDeviceControl: enter\n"));
181:
182: //
183: // Get a pointer to the device extension.
184: //
185:
186: deviceExtension = DeviceObject->DeviceExtension;
187:
188: //
189: // Initialize the returned Information field.
190: //
191:
192: Irp->IoStatus.Information = 0;
193:
194: //
195: // Get a pointer to the current parameters for this request. The
196: // information is contained in the current stack location.
197: //
198:
199: irpSp = IoGetCurrentIrpStackLocation(Irp);
200:
201: //
202: // Case on the device control subfunction that is being performed by the
203: // requestor.
204: //
205:
206: switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
207:
208: //
209: // Connect a mouse class device driver to the port driver.
210: //
211:
212: case IOCTL_INTERNAL_MOUSE_CONNECT:
213:
214: InpPrint((
215: 2,
216: "INPORT-InportInternalDeviceControl: mouse connect\n"
217: ));
218:
219: //
220: // Only allow one connection.
221: //
222: // FUTURE: Consider allowing multiple connections, just for
223: // the sake of generality?
224: //
225:
226: if (deviceExtension->ConnectData.ClassService
227: != NULL) {
228:
229: InpPrint((
230: 2,
231: "INPORT-InportInternalDeviceControl: error - already connected\n"
232: ));
233:
234: status = STATUS_SHARING_VIOLATION;
235: break;
236:
237: } else
238: if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
239: sizeof(CONNECT_DATA)) {
240:
241: InpPrint((
242: 2,
243: "INPORT-InportInternalDeviceControl: error - invalid buffer length\n"
244: ));
245:
246: status = STATUS_INVALID_PARAMETER;
247: break;
248: }
249:
250: //
251: // Copy the connection parameters to the device extension.
252: //
253:
254: deviceExtension->ConnectData =
255: *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
256:
257: //
258: // Reinitialize the port input data queue synchronously.
259: //
260:
261: KeSynchronizeExecution(
262: deviceExtension->InterruptObject,
263: (PKSYNCHRONIZE_ROUTINE) InpInitializeDataQueue,
264: (PVOID) deviceExtension
265: );
266:
267: //
268: // Set the completion status.
269: //
270:
271: status = STATUS_SUCCESS;
272: break;
273:
274: //
275: // Disconnect a mouse class device driver from the port driver.
276: //
277: // NOTE: Not implemented.
278: //
279:
280: case IOCTL_INTERNAL_MOUSE_DISCONNECT:
281:
282: InpPrint((
283: 2,
284: "INPORT-InportInternalDeviceControl: mouse disconnect\n"
285: ));
286:
287: //
288: // Perform a mouse interrupt disable call.
289: //
290:
291: //
292: // Clear the connection parameters in the device extension.
293: // NOTE: Must synchronize this with the mouse ISR.
294: //
295: //
296: //deviceExtension->ConnectData.ClassDeviceObject =
297: // Null;
298: //deviceExtension->ConnectData.ClassService =
299: // Null;
300:
301: //
302: // Set the completion status.
303: //
304:
305: status = STATUS_NOT_IMPLEMENTED;
306: break;
307:
308: //
309: // Enable mouse interrupts (mark the request pending and handle
310: // it in StartIo).
311: //
312:
313: case IOCTL_INTERNAL_MOUSE_ENABLE:
314:
315: InpPrint((
316: 2,
317: "INPORT-InportInternalDeviceControl: mouse enable\n"
318: ));
319:
320: status = STATUS_PENDING;
321: break;
322:
323: //
324: // Disable mouse interrupts (mark the request pending and handle
325: // it in StartIo).
326: //
327:
328: case IOCTL_INTERNAL_MOUSE_DISABLE:
329:
330: InpPrint((
331: 2,
332: "INPORT-InportInternalDeviceControl: mouse disable\n"
333: ));
334:
335: status = STATUS_PENDING;
336: break;
337:
338: //
339: // Query the mouse attributes. First check for adequate buffer
340: // length. Then, copy the mouse attributes from the device
341: // extension to the output buffer.
342: //
343:
344: case IOCTL_MOUSE_QUERY_ATTRIBUTES:
345:
346: InpPrint((
347: 2,
348: "INPORT-InportInternalDeviceControl: mouse query attributes\n"
349: ));
350:
351: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
352: sizeof(MOUSE_ATTRIBUTES)) {
353: status = STATUS_BUFFER_TOO_SMALL;
354: } else {
355:
356: //
357: // Copy the attributes from the DeviceExtension to the
358: // buffer.
359: //
360:
361: *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer =
362: deviceExtension->Configuration.MouseAttributes;
363:
364: Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
365: status = STATUS_SUCCESS;
366: }
367:
368: break;
369:
370: default:
371:
372: InpPrint((
373: 2,
374: "INPORT-InportInternalDeviceControl: INVALID REQUEST\n"
375: ));
376:
377: status = STATUS_INVALID_DEVICE_REQUEST;
378: break;
379: }
380:
381: Irp->IoStatus.Status = status;
382: if (status == STATUS_PENDING) {
383: IoMarkIrpPending(Irp);
384: IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
385: } else {
386: IoCompleteRequest(Irp, IO_NO_INCREMENT);
387: }
388:
389: InpPrint((2,"INPORT-InportInternalDeviceControl: exit\n"));
390:
391: return(status);
392:
393: }
394:
395: VOID
396: InportIsrDpc(
397: IN PKDPC Dpc,
398: IN PDEVICE_OBJECT DeviceObject,
399: IN PIRP Irp,
400: IN PVOID Context
401: )
402:
403: /*++
404:
405: Routine Description:
406:
407: This routine runs at DISPATCH_LEVEL IRQL to finish processing
408: mouse interrupts. It is queued in the mouse ISR. The real
409: work is done via a callback to the connected mouse class driver.
410:
411: Arguments:
412:
413: Dpc - Pointer to the DPC object.
414:
415: DeviceObject - Pointer to the device object.
416:
417: Irp - Pointer to the Irp.
418:
419: Context - Not used.
420:
421: Return Value:
422:
423: None.
424:
425: --*/
426:
427: {
428:
429: PDEVICE_EXTENSION deviceExtension;
430: GET_DATA_POINTER_CONTEXT getPointerContext;
431: SET_DATA_POINTER_CONTEXT setPointerContext;
432: VARIABLE_OPERATION_CONTEXT operationContext;
433: PVOID classService;
434: PVOID classDeviceObject;
435: LONG interlockedResult;
436: BOOLEAN moreDpcProcessing;
437: ULONG dataNotConsumed = 0;
438: ULONG inputDataConsumed = 0;
439: LARGE_INTEGER deltaTime;
440:
441: UNREFERENCED_PARAMETER(Dpc);
442: UNREFERENCED_PARAMETER(Irp);
443: UNREFERENCED_PARAMETER(Context);
444:
445: InpPrint((2, "INPORT-InportIsrDpc: enter\n"));
446:
447: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
448:
449: //
450: // Use DpcInterlockVariable to determine whether the DPC is running
451: // concurrently on another processor. We only want one instantiation
452: // of the DPC to actually do any work. DpcInterlockVariable is -1
453: // when no DPC is executing. We increment it, and if the result is
454: // zero then the current instantiation is the only one executing, and it
455: // is okay to proceed. Otherwise, we just return.
456: //
457: //
458:
459: operationContext.VariableAddress =
460: &deviceExtension->DpcInterlockVariable;
461: operationContext.Operation = IncrementOperation;
462: operationContext.NewValue = &interlockedResult;
463:
464: KeSynchronizeExecution(
465: deviceExtension->InterruptObject,
466: (PKSYNCHRONIZE_ROUTINE) InpDpcVariableOperation,
467: (PVOID) &operationContext
468: );
469:
470: moreDpcProcessing = (interlockedResult == 0)? TRUE:FALSE;
471:
472: while (moreDpcProcessing) {
473:
474: dataNotConsumed = 0;
475: inputDataConsumed = 0;
476:
477: //
478: // Get the port InputData queue pointers synchronously.
479: //
480:
481: getPointerContext.DeviceExtension = deviceExtension;
482: setPointerContext.DeviceExtension = deviceExtension;
483: setPointerContext.InputCount = 0;
484:
485: KeSynchronizeExecution(
486: deviceExtension->InterruptObject,
487: (PKSYNCHRONIZE_ROUTINE) InpGetDataQueuePointer,
488: (PVOID) &getPointerContext
489: );
490:
491: if (getPointerContext.InputCount != 0) {
492:
493: //
494: // Call the connected class driver's callback ISR with the
495: // port InputData queue pointers. If we have to wrap the queue,
496: // break the operation into two pieces, and call the class callback
497: // ISR once for each piece.
498: //
499:
500: classDeviceObject =
501: deviceExtension->ConnectData.ClassDeviceObject;
502: classService =
503: deviceExtension->ConnectData.ClassService;
504: ASSERT(classService != NULL);
505:
506: if (getPointerContext.DataOut >= getPointerContext.DataIn) {
507:
508: //
509: // We'll have to wrap the InputData circular buffer. Call
510: // the class callback ISR with the chunk of data starting at
511: // DataOut and ending at the end of the queue.
512: //
513:
514: InpPrint((
515: 2,
516: "INPORT-InportIsrDpc: calling class callback\n"
517: ));
518: InpPrint((
519: 2,
520: "INPORT-InportIsrDpc: with Start 0x%x and End 0x%x\n",
521: getPointerContext.DataOut,
522: deviceExtension->DataEnd
523: ));
524:
525: (*(PSERVICE_CALLBACK_ROUTINE) classService)(
526: classDeviceObject,
527: getPointerContext.DataOut,
528: deviceExtension->DataEnd,
529: &inputDataConsumed
530: );
531:
532: dataNotConsumed = (((PUCHAR)
533: deviceExtension->DataEnd -
534: (PUCHAR) getPointerContext.DataOut)
535: / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
536:
537: InpPrint((
538: 2,
539: "INPORT-InportIsrDpc: (Wrap) Call callback consumed %d items, left %d\n",
540: inputDataConsumed,
541: dataNotConsumed
542: ));
543:
544: setPointerContext.InputCount += inputDataConsumed;
545:
546: if (dataNotConsumed) {
547: setPointerContext.DataOut =
548: ((PUCHAR)getPointerContext.DataOut) +
549: (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
550: } else {
551: setPointerContext.DataOut =
552: deviceExtension->InputData;
553: getPointerContext.DataOut = setPointerContext.DataOut;
554: }
555: }
556:
557: //
558: // Call the class callback ISR with data remaining in the queue.
559: //
560:
561: if ((dataNotConsumed == 0) &&
562: (inputDataConsumed < getPointerContext.InputCount)){
563: InpPrint((
564: 2,
565: "INPORT-InportIsrDpc: calling class callback\n"
566: ));
567: InpPrint((
568: 2,
569: "INPORT-InportIsrDpc: with Start 0x%x and End 0x%x\n",
570: getPointerContext.DataOut,
571: getPointerContext.DataIn
572: ));
573:
574: (*(PSERVICE_CALLBACK_ROUTINE) classService)(
575: classDeviceObject,
576: getPointerContext.DataOut,
577: getPointerContext.DataIn,
578: &inputDataConsumed
579: );
580:
581: dataNotConsumed = (((PUCHAR) getPointerContext.DataIn -
582: (PUCHAR) getPointerContext.DataOut)
583: / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
584:
585: InpPrint((
586: 2,
587: "INPORT-InportIsrDpc: Call callback consumed %d items, left %d\n",
588: inputDataConsumed,
589: dataNotConsumed
590: ));
591:
592: setPointerContext.DataOut =
593: ((PUCHAR)getPointerContext.DataOut) +
594: (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
595: setPointerContext.InputCount += inputDataConsumed;
596:
597: }
598:
599: //
600: // Update the port InputData queue DataOut pointer and InputCount
601: // synchronously.
602: //
603:
604: KeSynchronizeExecution(
605: deviceExtension->InterruptObject,
606: (PKSYNCHRONIZE_ROUTINE) InpSetDataQueuePointer,
607: (PVOID) &setPointerContext
608: );
609:
610: }
611:
612: if (dataNotConsumed) {
613:
614: //
615: // The class driver was unable to consume all the data.
616: // Reset the interlocked variable to -1. We do not want
617: // to attempt to move more data to the class driver at this
618: // point, because it is already overloaded. Need to wait a
619: // while to give the Raw Input Thread a chance to read some
620: // of the data out of the class driver's queue. We accomplish
621: // this "wait" via a timer.
622: //
623:
624: InpPrint((2, "INPORT-InportIsrDpc: set timer in DPC\n"));
625:
626: operationContext.Operation = WriteOperation;
627: interlockedResult = -1;
628: operationContext.NewValue = &interlockedResult;
629:
630: KeSynchronizeExecution(
631: deviceExtension->InterruptObject,
632: (PKSYNCHRONIZE_ROUTINE) InpDpcVariableOperation,
633: (PVOID) &operationContext
634: );
635:
636: deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
637: deltaTime.HighPart = -1;
638:
639: (VOID) KeSetTimer(
640: &deviceExtension->DataConsumptionTimer,
641: deltaTime,
642: &deviceExtension->IsrDpcRetry
643: );
644:
645: moreDpcProcessing = FALSE;
646:
647: } else {
648:
649: //
650: // Decrement DpcInterlockVariable. If the result goes negative,
651: // then we're all finished processing the DPC. Otherwise, either
652: // the ISR incremented DpcInterlockVariable because it has more
653: // work for the ISR DPC to do, or a concurrent DPC executed on
654: // some processor while the current DPC was running (the
655: // concurrent DPC wouldn't have done any work). Make sure that
656: // the current DPC handles any extra work that is ready to be
657: // done.
658: //
659:
660: operationContext.Operation = DecrementOperation;
661: operationContext.NewValue = &interlockedResult;
662:
663: KeSynchronizeExecution(
664: deviceExtension->InterruptObject,
665: (PKSYNCHRONIZE_ROUTINE) InpDpcVariableOperation,
666: (PVOID) &operationContext
667: );
668:
669: if (interlockedResult != -1) {
670:
671: //
672: // The interlocked variable is still greater than or equal to
673: // zero. Reset it to zero, so that we execute the loop one
674: // more time (assuming no more DPCs execute and bump the
675: // variable up again).
676: //
677:
678: operationContext.Operation = WriteOperation;
679: interlockedResult = 0;
680: operationContext.NewValue = &interlockedResult;
681:
682: KeSynchronizeExecution(
683: deviceExtension->InterruptObject,
684: (PKSYNCHRONIZE_ROUTINE) InpDpcVariableOperation,
685: (PVOID) &operationContext
686: );
687:
688: InpPrint((2, "INPORT-InportIsrDpc: loop in DPC\n"));
689: } else {
690: moreDpcProcessing = FALSE;
691: }
692: }
693: }
694:
695: InpPrint((2, "INPORT-InportIsrDpc: exit\n"));
696:
697: }
698:
699: NTSTATUS
700: InportOpenClose(
701: IN PDEVICE_OBJECT DeviceObject,
702: IN PIRP Irp
703: )
704:
705: /*++
706:
707: Routine Description:
708:
709: This is the dispatch routine for create/open and close requests.
710: These requests complete successfully.
711:
712: Arguments:
713:
714: DeviceObject - Pointer to the device object.
715:
716: Irp - Pointer to the request packet.
717:
718: Return Value:
719:
720: Status is returned.
721:
722: --*/
723:
724: {
725:
726: UNREFERENCED_PARAMETER(DeviceObject);
727:
728: InpPrint((3,"INPORT-InportOpenClose: enter\n"));
729:
730: //
731: // Complete the request with successful status.
732: //
733:
734: Irp->IoStatus.Status = STATUS_SUCCESS;
735: Irp->IoStatus.Information = 0;
736: IoCompleteRequest(Irp, IO_NO_INCREMENT);
737:
738: InpPrint((3,"INPORT-InportOpenClose: exit\n"));
739:
740: return(STATUS_SUCCESS);
741:
742: } // end InportOpenClose
743:
744: VOID
745: InportStartIo(
746: IN PDEVICE_OBJECT DeviceObject,
747: IN PIRP Irp
748: )
749:
750: /*++
751:
752: Routine Description:
753:
754: This routine starts an I/O operation for the device.
755:
756: Arguments:
757:
758: DeviceObject - Pointer to the device object.
759:
760: Irp - Pointer to the request packet.
761:
762: Return Value:
763:
764: None.
765:
766: --*/
767:
768: {
769: PDEVICE_EXTENSION deviceExtension;
770: PIO_STACK_LOCATION irpSp;
771:
772: InpPrint((2, "INPORT-InportStartIo: enter\n"));
773:
774: deviceExtension = DeviceObject->DeviceExtension;
775:
776: //
777: // Bump the error log sequence number.
778: //
779:
780: deviceExtension->SequenceNumber += 1;
781:
782: //
783: // Get a pointer to the current parameters for this request. The
784: // information is contained in the current stack location.
785: //
786:
787: irpSp = IoGetCurrentIrpStackLocation(Irp);
788:
789: //
790: // We know we got here with an internal device control request. Switch
791: // on IoControlCode.
792: //
793:
794: switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
795:
796: //
797: // Enable mouse interrupts, by calling InpEnableInterrupts
798: // synchronously.
799: //
800:
801: case IOCTL_INTERNAL_MOUSE_ENABLE:
802:
803: KeSynchronizeExecution(
804: deviceExtension->InterruptObject,
805: (PKSYNCHRONIZE_ROUTINE) InpEnableInterrupts,
806: (PVOID) deviceExtension
807: );
808:
809: InpPrint((
810: 2,
811: "INPORT-InportStartIo: mouse enable (count %d)\n",
812: deviceExtension->MouseEnableCount
813: ));
814:
815: Irp->IoStatus.Status = STATUS_SUCCESS;
816:
817: //
818: // Complete the request.
819: //
820:
821: IoStartNextPacket(DeviceObject, FALSE);
822: IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
823:
824: break;
825:
826: //
827: // Disable mouse interrupts, by calling InpDisableInterrupts
828: // synchronously.
829: //
830:
831: case IOCTL_INTERNAL_MOUSE_DISABLE:
832:
833: InpPrint((2, "INPORT-InportStartIo: mouse disable"));
834:
835: if (deviceExtension->MouseEnableCount == 0) {
836:
837: //
838: // Mouse already disabled.
839: //
840:
841: InpPrint((2, " - error\n"));
842:
843: Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
844:
845: } else {
846:
847: //
848: // Disable mouse by calling InpDisableInterrupts.
849: //
850:
851: KeSynchronizeExecution(
852: deviceExtension->InterruptObject,
853: (PKSYNCHRONIZE_ROUTINE) InpDisableInterrupts,
854: (PVOID) deviceExtension
855: );
856:
857: InpPrint((
858: 2,
859: " (count %d)\n",
860: deviceExtension->MouseEnableCount
861: ));
862:
863: Irp->IoStatus.Status = STATUS_SUCCESS;
864: }
865:
866: //
867: // Complete the request.
868: //
869:
870: IoStartNextPacket(DeviceObject, FALSE);
871: IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
872:
873: break;
874:
875: default:
876:
877: InpPrint((2, "INPORT-InportStartIo: INVALID REQUEST\n"));
878:
879: //
880: // Log an internal error. Note that we're calling the
881: // error log DPC routine directly, rather than duplicating
882: // code.
883: //
884:
885: InportErrorLogDpc(
886: (PKDPC) NULL,
887: DeviceObject,
888: Irp,
889: (PVOID) (ULONG) INPORT_INVALID_STARTIO_REQUEST
890: );
891:
892: ASSERT(FALSE);
893: break;
894: }
895:
896: InpPrint((2, "INPORT-InportStartIo: exit\n"));
897:
898: return;
899: }
900:
901: #if DBG
902: VOID
903: InpDebugPrint(
904: ULONG DebugPrintLevel,
905: PCCHAR DebugMessage,
906: ...
907: )
908:
909: /*++
910:
911: Routine Description:
912:
913: Debug print routine.
914:
915: Arguments:
916:
917: Debug print level between 0 and 3, with 3 being the most verbose.
918:
919: Return Value:
920:
921: None.
922:
923: --*/
924:
925: {
926: va_list ap;
927:
928: va_start(ap, DebugMessage);
929:
930: if (DebugPrintLevel <= InportDebug) {
931:
932: char buffer[128];
933:
934: (VOID) vsprintf(buffer, DebugMessage, ap);
935:
936: DbgPrint(buffer);
937: }
938:
939: va_end(ap);
940:
941: }
942: #endif
943:
944: VOID
945: InpDpcVariableOperation(
946: IN PVOID Context
947: )
948:
949: /*++
950:
951: Routine Description:
952:
953: This routine is called synchronously by the ISR DPC to perform an
954: operation on the InterlockedDpcVariable. The operations that can be
955: performed include increment, decrement, write, and read. The ISR
956: itself reads and writes the InterlockedDpcVariable without calling this
957: routine.
958:
959: Arguments:
960:
961: Context - Pointer to a structure containing the address of the variable
962: to be operated on, the operation to perform, and the address at
963: which to copy the resulting value of the variable (the latter is also
964: used to pass in the value to write to the variable, on a write
965: operation).
966:
967: Return Value:
968:
969: None.
970:
971: --*/
972:
973: {
974: PVARIABLE_OPERATION_CONTEXT operationContext = Context;
975:
976: InpPrint((3,"INPORT-InpDpcVariableOperation: enter\n"));
977: InpPrint((
978: 3,
979: "\tPerforming %s at 0x%x (current value 0x%x)\n",
980: (operationContext->Operation == IncrementOperation)? "increment":
981: (operationContext->Operation == DecrementOperation)? "decrement":
982: (operationContext->Operation == WriteOperation)? "write":
983: (operationContext->Operation == ReadOperation)? "read":"",
984: operationContext->VariableAddress,
985: *(operationContext->VariableAddress)
986: ));
987:
988: //
989: // Perform the specified operation at the specified address.
990: //
991:
992: switch(operationContext->Operation) {
993: case IncrementOperation:
994: *(operationContext->VariableAddress) += 1;
995: break;
996: case DecrementOperation:
997: *(operationContext->VariableAddress) -= 1;
998: break;
999: case ReadOperation:
1000: break;
1001: case WriteOperation:
1002: InpPrint((
1003: 3,
1004: "\tWriting 0x%x\n",
1005: *(operationContext->NewValue)
1006: ));
1007: *(operationContext->VariableAddress) =
1008: *(operationContext->NewValue);
1009: break;
1010: default:
1011: ASSERT(FALSE);
1012: break;
1013: }
1014:
1015: *(operationContext->NewValue) = *(operationContext->VariableAddress);
1016:
1017: InpPrint((
1018: 3,
1019: "INPORT-InpDpcVariableOperation: exit with value 0x%x\n",
1020: *(operationContext->NewValue)
1021: ));
1022: }
1023:
1024: VOID
1025: InpGetDataQueuePointer(
1026: IN PVOID Context
1027: )
1028:
1029: /*++
1030:
1031: Routine Description:
1032:
1033: This routine is called synchronously to get the current DataIn and DataOut
1034: pointers for the port InputData queue.
1035:
1036: Arguments:
1037:
1038: Context - Pointer to a structure containing the device extension,
1039: address at which to store the current DataIn pointer, and the
1040: address at which to store the current DataOut pointer.
1041:
1042: Return Value:
1043:
1044: None.
1045:
1046: --*/
1047:
1048: {
1049: PDEVICE_EXTENSION deviceExtension;
1050:
1051: InpPrint((3,"INPORT-InpGetDataQueuePointer: enter\n"));
1052:
1053: //
1054: // Get address of device extension.
1055: //
1056:
1057: deviceExtension = (PDEVICE_EXTENSION)
1058: ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
1059:
1060: //
1061: // Get the DataIn and DataOut pointers.
1062: //
1063:
1064: InpPrint((
1065: 3,
1066: "INPORT-InpGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n",
1067: deviceExtension->DataIn,
1068: deviceExtension->DataOut
1069: ));
1070: ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn = deviceExtension->DataIn;
1071: ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut = deviceExtension->DataOut;
1072: ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount =
1073: deviceExtension->InputCount;
1074:
1075: InpPrint((3,"INPORT-InpGetDataQueuePointer: exit\n"));
1076: }
1077:
1078: VOID
1079: InpInitializeDataQueue (
1080: IN PVOID Context
1081: )
1082:
1083: /*++
1084:
1085: Routine Description:
1086:
1087: This routine initializes the input data queue. It is called
1088: via KeSynchronization, except when called from the initialization routine.
1089:
1090: Arguments:
1091:
1092: Context - Pointer to the device extension.
1093:
1094: Return Value:
1095:
1096: None.
1097:
1098: --*/
1099:
1100: {
1101:
1102: PDEVICE_EXTENSION deviceExtension;
1103:
1104: InpPrint((3,"INPORT-InpInitializeDataQueue: enter\n"));
1105:
1106: //
1107: // Get address of device extension.
1108: //
1109:
1110: deviceExtension = (PDEVICE_EXTENSION) Context;
1111:
1112: //
1113: // Initialize the input data queue.
1114: //
1115:
1116: deviceExtension->InputCount = 0;
1117: deviceExtension->DataIn = deviceExtension->InputData;
1118: deviceExtension->DataOut = deviceExtension->InputData;
1119:
1120: deviceExtension->OkayToLogOverflow = TRUE;
1121:
1122: InpPrint((3,"INPORT-InpInitializeDataQueue: exit\n"));
1123:
1124: }
1125:
1126: VOID
1127: InpSetDataQueuePointer(
1128: IN PVOID Context
1129: )
1130:
1131: /*++
1132:
1133: Routine Description:
1134:
1135: This routine is called synchronously to set the DataOut pointer
1136: and InputCount for the port InputData queue.
1137:
1138: Arguments:
1139:
1140: Context - Pointer to a structure containing the device extension
1141: and the new DataOut value for the port InputData queue.
1142:
1143: Return Value:
1144:
1145: None.
1146:
1147: --*/
1148:
1149: {
1150: PDEVICE_EXTENSION deviceExtension;
1151:
1152: InpPrint((3,"INPORT-InpSetDataQueuePointer: enter\n"));
1153:
1154: //
1155: // Get address of device extension.
1156: //
1157:
1158: deviceExtension = (PDEVICE_EXTENSION)
1159: ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
1160:
1161: //
1162: // Set the DataOut pointer.
1163: //
1164:
1165: InpPrint((
1166: 3,
1167: "INPORT-InpSetDataQueuePointer: old mouse DataOut 0x%x, InputCount %d\n",
1168: deviceExtension->DataOut,
1169: deviceExtension->InputCount
1170: ));
1171: deviceExtension->DataOut = ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut;
1172: deviceExtension->InputCount -=
1173: ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount;
1174:
1175: if (deviceExtension->InputCount == 0) {
1176:
1177: //
1178: // Reset the flag that determines whether it is time to log
1179: // queue overflow errors. We don't want to log errors too often.
1180: // Instead, log an error on the first overflow that occurs after
1181: // the ring buffer has been emptied, and then stop logging errors
1182: // until it gets cleared out and overflows again.
1183: //
1184:
1185: InpPrint((
1186: 1,
1187: "INPORT-InpSetDataQueuePointer: Okay to log overflow\n"
1188: ));
1189: deviceExtension->OkayToLogOverflow = TRUE;
1190: }
1191:
1192: InpPrint((
1193: 3,
1194: "INPORT-InpSetDataQueuePointer: new mouse DataOut 0x%x, InputCount %d\n",
1195: deviceExtension->DataOut,
1196: deviceExtension->InputCount
1197: ));
1198:
1199: InpPrint((3,"INPORT-InpSetDataQueuePointer: exit\n"));
1200: }
1201:
1202: BOOLEAN
1203: InpWriteDataToQueue(
1204: PDEVICE_EXTENSION DeviceExtension,
1205: IN PMOUSE_INPUT_DATA InputData
1206: )
1207:
1208: /*++
1209:
1210: Routine Description:
1211:
1212: This routine adds input data from the mouse to the InputData queue.
1213:
1214: Arguments:
1215:
1216: DeviceExtension - Pointer to the device extension.
1217:
1218: InputData - Pointer to the data to add to the InputData queue.
1219:
1220: Return Value:
1221:
1222: Returns TRUE if the data was added, otherwise FALSE.
1223:
1224: --*/
1225:
1226: {
1227:
1228: InpPrint((2,"INPORT-InpWriteDataToQueue: enter\n"));
1229: InpPrint((
1230: 3,
1231: "INPORT-InpWriteDataToQueue: DataIn 0x%x, DataOut 0x%x\n",
1232: DeviceExtension->DataIn,
1233: DeviceExtension->DataOut
1234: ));
1235: InpPrint((
1236: 3,
1237: "INPORT-InpWriteDataToQueue: InputCount %d\n",
1238: DeviceExtension->InputCount
1239: ));
1240:
1241: //
1242: // Check for full input data queue.
1243: //
1244:
1245: if ((DeviceExtension->DataIn == DeviceExtension->DataOut) &&
1246: (DeviceExtension->InputCount != 0)) {
1247:
1248: //
1249: // The input data queue is full. Intentionally ignore
1250: // the new data.
1251: //
1252:
1253: InpPrint((1,"INPORT-InpWriteDataToQueue: OVERFLOW\n"));
1254: return(FALSE);
1255:
1256: } else {
1257: *(DeviceExtension->DataIn) = *InputData;
1258: DeviceExtension->InputCount += 1;
1259: DeviceExtension->DataIn++;
1260: InpPrint((
1261: 2,
1262: "INPORT-InpWriteDataToQueue: new InputCount %d\n",
1263: DeviceExtension->InputCount
1264: ));
1265: if (DeviceExtension->DataIn ==
1266: DeviceExtension->DataEnd) {
1267: InpPrint((2,"INPORT-InpWriteDataToQueue: wrap buffer\n"));
1268: DeviceExtension->DataIn = DeviceExtension->InputData;
1269: }
1270: }
1271:
1272: InpPrint((2,"INPORT-InpWriteDataToQueue: exit\n"));
1273:
1274: return(TRUE);
1275: }
1276:
1277: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.