|
|
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.