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