|
|
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: sermdep.c ! 9: ! 10: Abstract: ! 11: ! 12: The initialization and hardware-dependent portions of ! 13: the Microsoft serial (i8250) mouse port driver. Modifications ! 14: to support new mice similar to the serial mouse should be ! 15: localized to this file. ! 16: ! 17: Environment: ! 18: ! 19: Kernel mode only. ! 20: ! 21: Notes: ! 22: ! 23: NOTES: (Future/outstanding issues) ! 24: ! 25: - Powerfail not implemented. ! 26: ! 27: - Consolidate duplicate code, where possible and appropriate. ! 28: ! 29: - The serial ballpoint is supported. However, Windows USER does not ! 30: intend (right now) to use the ballpoint in anything except mouse ! 31: emulation mode. In ballpoint mode, there is extra functionality that ! 32: would need to be supported. E.g., the driver would need to pass ! 33: back extra button information from the 4th byte of the ballpoint ! 34: data packet. Windows USER would need/want to allow the user to select ! 35: which buttons are used, what the orientation of the ball is (esp. ! 36: important for lefthanders), sensitivity, and acceleration profile. ! 37: ! 38: ! 39: Revision History: ! 40: ! 41: ! 42: --*/ ! 43: ! 44: #include "stdarg.h" ! 45: #include "stdio.h" ! 46: #include "string.h" ! 47: #include "ntddk.h" ! 48: #include "sermouse.h" ! 49: #include "sermlog.h" ! 50: #include "cseries.h" ! 51: #include "mseries.h" ! 52: #include "debug.h" ! 53: ! 54: // ! 55: // Use the alloc_text pragma to specify the driver initialization routines ! 56: // (they can be paged out). ! 57: // ! 58: ! 59: #ifdef ALLOC_PRAGMA ! 60: #pragma alloc_text(init,DriverEntry) ! 61: #pragma alloc_text(init,SerMouConfiguration) ! 62: #pragma alloc_text(init,SerMouPeripheralCallout) ! 63: #pragma alloc_text(init,SerMouServiceParameters) ! 64: #pragma alloc_text(init,SerMouInitializeHardware) ! 65: #pragma alloc_text(init,SerMouBuildResourceList) ! 66: #endif ! 67: ! 68: ! 69: NTSTATUS ! 70: DriverEntry( ! 71: IN PDRIVER_OBJECT DriverObject, ! 72: IN PUNICODE_STRING RegistryPath ! 73: ) ! 74: ! 75: /*++ ! 76: ! 77: Routine Description: ! 78: ! 79: This routine initializes the serial (i8250) mouse port driver. ! 80: ! 81: Arguments: ! 82: ! 83: DriverObject - Pointer to driver object created by system. ! 84: ! 85: RegistryPath - Pointer to the Unicode name of the registry path ! 86: for this driver. ! 87: ! 88: Return Value: ! 89: ! 90: The function value is the final status from the initialization operation. ! 91: ! 92: --*/ ! 93: ! 94: { ! 95: PDEVICE_OBJECT portDeviceObject = NULL; ! 96: PDEVICE_EXTENSION deviceExtension = NULL; ! 97: DEVICE_EXTENSION tmpDeviceExtension; ! 98: NTSTATUS status = STATUS_SUCCESS; ! 99: KIRQL coordinatorIrql = 0; ! 100: ULONG interruptVector; ! 101: KIRQL interruptLevel; ! 102: KAFFINITY affinity; ! 103: PIO_ERROR_LOG_PACKET errorLogEntry; ! 104: ULONG uniqueErrorValue; ! 105: NTSTATUS errorCode = STATUS_SUCCESS; ! 106: ULONG dumpCount = 0; ! 107: PCM_RESOURCE_LIST resources = NULL; ! 108: ULONG resourceListSize = 0; ! 109: BOOLEAN conflictDetected; ! 110: ULONG addressSpace; ! 111: PHYSICAL_ADDRESS cardAddress; ! 112: ULONG i; ! 113: UNICODE_STRING fullDeviceName; ! 114: UNICODE_STRING baseDeviceName; ! 115: UNICODE_STRING deviceNameSuffix; ! 116: UNICODE_STRING registryPath; ! 117: ! 118: #define NAME_MAX 256 ! 119: WCHAR nameBuffer[NAME_MAX]; ! 120: ! 121: #define DUMP_COUNT 4 ! 122: ULONG dumpData[DUMP_COUNT]; ! 123: ! 124: SerMouPrint((1,"\n\nSERMOUSE-SerialMouseInitialize: enter\n")); ! 125: ! 126: // ! 127: // Zero-initialize various structures. ! 128: // ! 129: ! 130: RtlZeroMemory(&tmpDeviceExtension, sizeof(tmpDeviceExtension)); ! 131: for (i = 0; i < DUMP_COUNT; i++) ! 132: dumpData[i] = 0; ! 133: ! 134: fullDeviceName.MaximumLength = 0; ! 135: deviceNameSuffix.MaximumLength = 0; ! 136: registryPath.MaximumLength = 0; ! 137: ! 138: RtlZeroMemory(nameBuffer, NAME_MAX * sizeof(WCHAR)); ! 139: baseDeviceName.Buffer = nameBuffer; ! 140: baseDeviceName.Length = 0; ! 141: baseDeviceName.MaximumLength = NAME_MAX * sizeof(WCHAR); ! 142: ! 143: // ! 144: // Need to ensure that the registry path is null-terminated. ! 145: // Allocate pool to hold a null-terminated copy of the path. ! 146: // ! 147: ! 148: registryPath.Buffer = ExAllocatePool( ! 149: PagedPool, ! 150: RegistryPath->Length + sizeof(UNICODE_NULL) ! 151: ); ! 152: ! 153: if (!registryPath.Buffer) { ! 154: SerMouPrint(( ! 155: 1, ! 156: "SERMOUSE-SerialMouseInitialize: Couldn't allocate pool for registry path\n" ! 157: )); ! 158: ! 159: status = STATUS_UNSUCCESSFUL; ! 160: errorCode = SERMOUSE_INSUFFICIENT_RESOURCES; ! 161: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 2; ! 162: dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL); ! 163: dumpCount = 1; ! 164: goto SerialMouseInitializeExit; ! 165: ! 166: } else { ! 167: ! 168: registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL); ! 169: registryPath.MaximumLength = registryPath.Length; ! 170: ! 171: RtlZeroMemory( ! 172: registryPath.Buffer, ! 173: registryPath.Length ! 174: ); ! 175: ! 176: RtlMoveMemory( ! 177: registryPath.Buffer, ! 178: RegistryPath->Buffer, ! 179: RegistryPath->Length ! 180: ); ! 181: ! 182: } ! 183: ! 184: // ! 185: // Get the configuration information for this driver. ! 186: // ! 187: ! 188: SerMouConfiguration(&tmpDeviceExtension, ®istryPath, &baseDeviceName); ! 189: ! 190: if (tmpDeviceExtension.HardwarePresent == 0) { ! 191: ! 192: // ! 193: // There is no serial mouse attached. Return ! 194: // unsuccessful status. ! 195: // ! 196: ! 197: SerMouPrint((1,"SERMOUSE-SerialMouseInitialize: No mouse attached.\n")); ! 198: status = STATUS_NO_SUCH_DEVICE; ! 199: errorCode = SERMOUSE_NO_SUCH_DEVICE; ! 200: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 4; ! 201: dumpCount = 0; ! 202: goto SerialMouseInitializeExit; ! 203: ! 204: } ! 205: ! 206: // ! 207: // Set up space for the port's device object suffix. Note that ! 208: // we overallocate space for the suffix string because it is much ! 209: // easier than figuring out exactly how much space is required. ! 210: // The storage gets freed at the end of driver initialization, so ! 211: // who cares... ! 212: // ! 213: ! 214: RtlInitUnicodeString( ! 215: &deviceNameSuffix, ! 216: NULL ! 217: ); ! 218: ! 219: deviceNameSuffix.MaximumLength = POINTER_PORTS_MAXIMUM * sizeof(WCHAR); ! 220: deviceNameSuffix.MaximumLength += sizeof(UNICODE_NULL); ! 221: ! 222: deviceNameSuffix.Buffer = ExAllocatePool( ! 223: PagedPool, ! 224: deviceNameSuffix.MaximumLength ! 225: ); ! 226: ! 227: if (!deviceNameSuffix.Buffer) { ! 228: ! 229: SerMouPrint(( ! 230: 1, ! 231: "SERMOUSE-SerialMouseInitialize: Couldn't allocate string for device object suffix\n" ! 232: )); ! 233: ! 234: status = STATUS_UNSUCCESSFUL; ! 235: errorCode = SERMOUSE_INSUFFICIENT_RESOURCES; ! 236: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 6; ! 237: dumpData[0] = (ULONG) deviceNameSuffix.MaximumLength; ! 238: dumpCount = 1; ! 239: goto SerialMouseInitializeExit; ! 240: ! 241: } ! 242: ! 243: RtlZeroMemory( ! 244: deviceNameSuffix.Buffer, ! 245: deviceNameSuffix.MaximumLength ! 246: ); ! 247: ! 248: // ! 249: // Set up space for the port's full device object name. ! 250: // ! 251: ! 252: RtlInitUnicodeString( ! 253: &fullDeviceName, ! 254: NULL ! 255: ); ! 256: ! 257: fullDeviceName.MaximumLength = sizeof(L"\\Device\\") + ! 258: baseDeviceName.Length + ! 259: deviceNameSuffix.MaximumLength; ! 260: ! 261: ! 262: fullDeviceName.Buffer = ExAllocatePool( ! 263: PagedPool, ! 264: fullDeviceName.MaximumLength ! 265: ); ! 266: ! 267: if (!fullDeviceName.Buffer) { ! 268: ! 269: SerMouPrint(( ! 270: 1, ! 271: "SERMOUSE-SerialMouseInitialize: Couldn't allocate string for device object name\n" ! 272: )); ! 273: ! 274: status = STATUS_UNSUCCESSFUL; ! 275: errorCode = SERMOUSE_INSUFFICIENT_RESOURCES; ! 276: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 8; ! 277: dumpData[0] = (ULONG) fullDeviceName.MaximumLength; ! 278: dumpCount = 1; ! 279: goto SerialMouseInitializeExit; ! 280: ! 281: } ! 282: ! 283: RtlZeroMemory( ! 284: fullDeviceName.Buffer, ! 285: fullDeviceName.MaximumLength ! 286: ); ! 287: RtlAppendUnicodeToString( ! 288: &fullDeviceName, ! 289: L"\\Device\\" ! 290: ); ! 291: RtlAppendUnicodeToString( ! 292: &fullDeviceName, ! 293: baseDeviceName.Buffer ! 294: ); ! 295: ! 296: for (i = 0; i < POINTER_PORTS_MAXIMUM; i++) { ! 297: ! 298: // ! 299: // Append the suffix to the device object name string. E.g., turn ! 300: // \Device\PointerPort into \Device\PointerPort0. Then we attempt ! 301: // to create the device object. If the device object already ! 302: // exists (because it was already created by another port driver), ! 303: // increment the suffix and try again. ! 304: // ! 305: ! 306: status = RtlIntegerToUnicodeString( ! 307: i, ! 308: 10, ! 309: &deviceNameSuffix ! 310: ); ! 311: ! 312: if (!NT_SUCCESS(status)) { ! 313: break; ! 314: } ! 315: ! 316: RtlAppendUnicodeStringToString( ! 317: &fullDeviceName, ! 318: &deviceNameSuffix ! 319: ); ! 320: ! 321: SerMouPrint(( ! 322: 1, ! 323: "SERMOUSE-SerialMouseInitialize: Creating device object named %ws\n", ! 324: fullDeviceName.Buffer ! 325: )); ! 326: ! 327: // ! 328: // Create a non-exclusive device object for the serial mouse ! 329: // port device. ! 330: // ! 331: ! 332: status = IoCreateDevice( ! 333: DriverObject, ! 334: sizeof(DEVICE_EXTENSION), ! 335: &fullDeviceName, ! 336: FILE_DEVICE_SERIAL_MOUSE_PORT, ! 337: 0, ! 338: FALSE, ! 339: &portDeviceObject ! 340: ); ! 341: ! 342: if (NT_SUCCESS(status)) { ! 343: ! 344: // ! 345: // We've successfully created a device object. ! 346: // ! 347: ! 348: tmpDeviceExtension.UnitId = i; ! 349: break; ! 350: } else { ! 351: ! 352: // ! 353: // We'll increment the suffix and try again. Note that we reset ! 354: // the length of the string here to get back to the beginning ! 355: // of the suffix portion of the name. Do not bother to ! 356: // zero the suffix, though, because the string for the ! 357: // incremented suffix will be at least as long as the previous ! 358: // one. ! 359: // ! 360: ! 361: fullDeviceName.Length -= deviceNameSuffix.Length; ! 362: } ! 363: } ! 364: ! 365: if (!NT_SUCCESS(status)) { ! 366: SerMouPrint(( ! 367: 1, ! 368: "SERMOUSE-SerialMouseInitialize: Could not create port device object = %ws\n", ! 369: fullDeviceName.Buffer ! 370: )); ! 371: errorCode = SERMOUSE_INSUFFICIENT_RESOURCES; ! 372: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 10; ! 373: dumpData[0] = (ULONG) i; ! 374: dumpCount = 1; ! 375: goto SerialMouseInitializeExit; ! 376: } ! 377: ! 378: // ! 379: // Do buffered I/O. I.e., the I/O system will copy to/from user data ! 380: // from/to a system buffer. ! 381: // ! 382: ! 383: portDeviceObject->Flags |= DO_BUFFERED_IO; ! 384: ! 385: // ! 386: // Set up the device extension. ! 387: // ! 388: ! 389: deviceExtension = ! 390: (PDEVICE_EXTENSION) portDeviceObject->DeviceExtension; ! 391: *deviceExtension = tmpDeviceExtension; ! 392: deviceExtension->DeviceObject = portDeviceObject; ! 393: ! 394: // ! 395: // Set up the device resource list prior to reporting resource usage. ! 396: // ! 397: ! 398: SerMouBuildResourceList(deviceExtension, &resources, &resourceListSize); ! 399: ! 400: // ! 401: // Report resource usage for the registry. ! 402: // ! 403: ! 404: IoReportResourceUsage( ! 405: &baseDeviceName, ! 406: DriverObject, ! 407: NULL, ! 408: 0, ! 409: portDeviceObject, ! 410: resources, ! 411: resourceListSize, ! 412: FALSE, ! 413: &conflictDetected ! 414: ); ! 415: ! 416: if (conflictDetected) { ! 417: ! 418: // ! 419: // Some other device already owns the ports or interrupts. ! 420: // Fatal error. ! 421: // ! 422: ! 423: SerMouPrint(( ! 424: 1, ! 425: "SERMOUSE-SerialMouseInitialize: Resource usage conflict\n" ! 426: )); ! 427: ! 428: // ! 429: // Log an error. ! 430: // ! 431: ! 432: errorCode = SERMOUSE_RESOURCE_CONFLICT; ! 433: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 15; ! 434: dumpData[0] = (ULONG) ! 435: resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level; ! 436: dumpData[1] = (ULONG) ! 437: resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector; ! 438: dumpData[2] = (ULONG) ! 439: resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Level; ! 440: dumpData[3] = (ULONG) ! 441: resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Vector; ! 442: dumpCount = 4; ! 443: ! 444: goto SerialMouseInitializeExit; ! 445: ! 446: } ! 447: ! 448: // ! 449: // Map the serial mouse controller registers. ! 450: // ! 451: ! 452: addressSpace = (deviceExtension->Configuration.PortList[0].Flags ! 453: & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO? 1:0; ! 454: ! 455: HalTranslateBusAddress( ! 456: deviceExtension->Configuration.InterfaceType, ! 457: deviceExtension->Configuration.BusNumber, ! 458: deviceExtension->Configuration.PortList[0].u.Port.Start, ! 459: &addressSpace, ! 460: &cardAddress ! 461: ); ! 462: ! 463: if (!addressSpace) { ! 464: ! 465: deviceExtension->Configuration.UnmapRegistersRequired = TRUE; ! 466: deviceExtension->Configuration.DeviceRegisters[0] = ! 467: MmMapIoSpace( ! 468: cardAddress, ! 469: deviceExtension->Configuration.PortList[0].u.Port.Length, ! 470: FALSE ! 471: ); ! 472: ! 473: } else { ! 474: ! 475: deviceExtension->Configuration.UnmapRegistersRequired = FALSE; ! 476: deviceExtension->Configuration.DeviceRegisters[0] = ! 477: (PVOID)cardAddress.LowPart; ! 478: ! 479: } ! 480: ! 481: if (!deviceExtension->Configuration.DeviceRegisters[0]) { ! 482: ! 483: SerMouPrint(( ! 484: 1, ! 485: "SERMOUSE-SerialMouseInitialize: Couldn't map the device registers.\n" ! 486: )); ! 487: deviceExtension->Configuration.UnmapRegistersRequired = FALSE; ! 488: status = STATUS_NONE_MAPPED; ! 489: ! 490: // ! 491: // Log an error. ! 492: // ! 493: ! 494: errorCode = SERMOUSE_REGISTERS_NOT_MAPPED; ! 495: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 20; ! 496: dumpData[0] = cardAddress.LowPart; ! 497: dumpCount = 1; ! 498: ! 499: goto SerialMouseInitializeExit; ! 500: ! 501: } else { ! 502: SerMouPrint(( ! 503: 1, ! 504: "SERMOUSE-SerialMouseInitialize: Mapped device registers to 0x%x.\n", ! 505: deviceExtension->Configuration.DeviceRegisters[0] ! 506: )); ! 507: } ! 508: ! 509: // ! 510: // Initialize the serial mouse hardware to default values for the mouse. ! 511: // Note that interrupts remain disabled until the class driver ! 512: // requests a MOUSE_CONNECT internal device control. ! 513: // ! 514: ! 515: status = SerMouInitializeHardware(portDeviceObject); ! 516: ! 517: if (!NT_SUCCESS(status)) { ! 518: SerMouPrint(( ! 519: 1, ! 520: "SERMOUSE-SerialMouseInitialize: Could not initialize hardware\n" ! 521: )); ! 522: goto SerialMouseInitializeExit; ! 523: } ! 524: ! 525: // ! 526: // Allocate the ring buffer for the mouse input data. ! 527: // ! 528: ! 529: deviceExtension->InputData = ! 530: ExAllocatePool( ! 531: NonPagedPool, ! 532: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength ! 533: ); ! 534: ! 535: if (!deviceExtension->InputData) { ! 536: ! 537: // ! 538: // Could not allocate memory for the mouse data queue. ! 539: // ! 540: ! 541: SerMouPrint(( ! 542: 1, ! 543: "SERMOUSE-SerialMouseInitialize: Could not allocate mouse input data queue\n" ! 544: )); ! 545: ! 546: status = STATUS_INSUFFICIENT_RESOURCES; ! 547: ! 548: // ! 549: // Log an error. ! 550: // ! 551: ! 552: errorCode = SERMOUSE_NO_BUFFER_ALLOCATED; ! 553: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 30; ! 554: dumpData[0] = ! 555: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength; ! 556: dumpCount = 1; ! 557: ! 558: goto SerialMouseInitializeExit; ! 559: } ! 560: ! 561: deviceExtension->DataEnd = ! 562: (PMOUSE_INPUT_DATA) ((PCHAR) (deviceExtension->InputData) ! 563: + deviceExtension->Configuration.MouseAttributes.InputDataQueueLength); ! 564: ! 565: // ! 566: // Zero the mouse input data ring buffer. ! 567: // ! 568: ! 569: RtlZeroMemory( ! 570: deviceExtension->InputData, ! 571: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength ! 572: ); ! 573: ! 574: // ! 575: // Initialize the connection data. ! 576: // ! 577: ! 578: deviceExtension->ConnectData.ClassDeviceObject = NULL; ! 579: deviceExtension->ConnectData.ClassService = NULL; ! 580: ! 581: // ! 582: // Initialize the input data queue. ! 583: // ! 584: ! 585: SerMouInitializeDataQueue((PVOID) deviceExtension); ! 586: ! 587: // ! 588: // Initialize the port ISR DPC. The ISR DPC is responsible for ! 589: // calling the connected class driver's callback routine to process ! 590: // the input data queue. ! 591: // ! 592: ! 593: deviceExtension->DpcInterlockVariable = -1; ! 594: ! 595: KeInitializeSpinLock(&deviceExtension->SpinLock); ! 596: ! 597: KeInitializeDpc( ! 598: &deviceExtension->IsrDpc, ! 599: (PKDEFERRED_ROUTINE) SerialMouseIsrDpc, ! 600: portDeviceObject ! 601: ); ! 602: ! 603: KeInitializeDpc( ! 604: &deviceExtension->IsrDpcRetry, ! 605: (PKDEFERRED_ROUTINE) SerialMouseIsrDpc, ! 606: portDeviceObject ! 607: ); ! 608: ! 609: // ! 610: // Initialize the mouse data consumption timer. ! 611: // ! 612: ! 613: KeInitializeTimer(&deviceExtension->DataConsumptionTimer); ! 614: ! 615: // ! 616: // Initialize the port DPC queue to log overrun and internal ! 617: // driver errors. ! 618: // ! 619: ! 620: KeInitializeDpc( ! 621: &deviceExtension->ErrorLogDpc, ! 622: (PKDEFERRED_ROUTINE) SerialMouseErrorLogDpc, ! 623: portDeviceObject ! 624: ); ! 625: ! 626: // ! 627: // From the Hal, get the interrupt vector and level. ! 628: // ! 629: ! 630: interruptVector = HalGetInterruptVector( ! 631: deviceExtension->Configuration.InterfaceType, ! 632: deviceExtension->Configuration.BusNumber, ! 633: deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Level, ! 634: deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Vector, ! 635: &interruptLevel, ! 636: &affinity ! 637: ); ! 638: ! 639: // ! 640: // Initialize and connect the interrupt object for the mouse. ! 641: // ! 642: ! 643: status = IoConnectInterrupt( ! 644: &(deviceExtension->InterruptObject), ! 645: (PKSERVICE_ROUTINE) SerialMouseInterruptService, ! 646: (PVOID) portDeviceObject, ! 647: (PKSPIN_LOCK)NULL, ! 648: interruptVector, ! 649: interruptLevel, ! 650: interruptLevel, ! 651: deviceExtension->Configuration.MouseInterrupt.Flags ! 652: == CM_RESOURCE_INTERRUPT_LATCHED ? Latched:LevelSensitive, ! 653: deviceExtension->Configuration.MouseInterrupt.ShareDisposition, ! 654: affinity, ! 655: deviceExtension->Configuration.FloatingSave ! 656: ); ! 657: ! 658: if (!NT_SUCCESS(status)) { ! 659: ! 660: // ! 661: // Failed to install. Free up resources before exiting. ! 662: // ! 663: ! 664: SerMouPrint(( ! 665: 1, ! 666: "SERMOUSE-SerialMouseInitialize: Could not connect mouse interrupt\n" ! 667: )); ! 668: ! 669: // ! 670: // Log an error. ! 671: // ! 672: ! 673: errorCode = SERMOUSE_NO_INTERRUPT_CONNECTED; ! 674: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 40; ! 675: dumpData[0] = interruptLevel; ! 676: dumpCount = 1; ! 677: ! 678: goto SerialMouseInitializeExit; ! 679: ! 680: } ! 681: ! 682: // ! 683: // Once initialization is finished, load the device map information ! 684: // into the registry so that setup can determine which pointer port ! 685: // is active. ! 686: // ! 687: ! 688: status = RtlWriteRegistryValue( ! 689: RTL_REGISTRY_DEVICEMAP, ! 690: baseDeviceName.Buffer, ! 691: fullDeviceName.Buffer, ! 692: REG_SZ, ! 693: registryPath.Buffer, ! 694: registryPath.Length ! 695: ); ! 696: ! 697: if (!NT_SUCCESS(status)) { ! 698: ! 699: SerMouPrint(( ! 700: 1, ! 701: "SERMOUSE-SerialMouseInitialize: Could not store name in DeviceMap\n" ! 702: )); ! 703: ! 704: errorCode = SERMOUSE_NO_DEVICEMAP_CREATED; ! 705: uniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 50; ! 706: dumpCount = 0; ! 707: ! 708: goto SerialMouseInitializeExit; ! 709: ! 710: } else { ! 711: ! 712: SerMouPrint(( ! 713: 1, ! 714: "SERMOUSE-SerialMouseInitialize: Stored name in DeviceMap\n" ! 715: )); ! 716: } ! 717: ! 718: ASSERT(status == STATUS_SUCCESS); ! 719: ! 720: // ! 721: // Set up the device driver entry points. ! 722: // ! 723: ! 724: DriverObject->DriverStartIo = SerialMouseStartIo; ! 725: DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialMouseOpenClose; ! 726: DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialMouseOpenClose; ! 727: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ! 728: SerialMouseFlush; ! 729: DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ! 730: SerialMouseInternalDeviceControl; ! 731: // ! 732: // NOTE: Don't allow this driver to unload. Otherwise, we would set ! 733: // DriverObject->DriverUnload = SerialMouseUnload. ! 734: // ! 735: ! 736: SerialMouseInitializeExit: ! 737: ! 738: // ! 739: // Log an error, if necessary. ! 740: // ! 741: ! 742: if (errorCode != STATUS_SUCCESS) { ! 743: errorLogEntry = (PIO_ERROR_LOG_PACKET) ! 744: IoAllocateErrorLogEntry( ! 745: (portDeviceObject == NULL) ? ! 746: (PVOID) DriverObject : (PVOID) portDeviceObject, ! 747: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) ! 748: + (dumpCount * sizeof(ULONG))) ! 749: ); ! 750: ! 751: if (errorLogEntry != NULL) { ! 752: ! 753: errorLogEntry->ErrorCode = errorCode; ! 754: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG); ! 755: errorLogEntry->SequenceNumber = 0; ! 756: errorLogEntry->MajorFunctionCode = 0; ! 757: errorLogEntry->IoControlCode = 0; ! 758: errorLogEntry->RetryCount = 0; ! 759: errorLogEntry->UniqueErrorValue = uniqueErrorValue; ! 760: errorLogEntry->FinalStatus = status; ! 761: for (i = 0; i < dumpCount; i++) ! 762: errorLogEntry->DumpData[i] = dumpData[i]; ! 763: ! 764: IoWriteErrorLogEntry(errorLogEntry); ! 765: } ! 766: } ! 767: ! 768: if (!NT_SUCCESS(status)) { ! 769: ! 770: // ! 771: // The initialization failed. Cleanup resources before exiting. ! 772: // ! 773: // ! 774: // Note: No need/way to undo the KeInitializeDpc or ! 775: // KeInitializeTimer calls. ! 776: // ! 777: ! 778: if (resources) { ! 779: ! 780: // ! 781: // Call IoReportResourceUsage to remove the resources from ! 782: // the map. ! 783: // ! 784: ! 785: resources->Count = 0; ! 786: ! 787: IoReportResourceUsage( ! 788: &baseDeviceName, ! 789: DriverObject, ! 790: NULL, ! 791: 0, ! 792: portDeviceObject, ! 793: resources, ! 794: resourceListSize, ! 795: FALSE, ! 796: &conflictDetected ! 797: ); ! 798: ! 799: } ! 800: ! 801: if (deviceExtension) { ! 802: if (deviceExtension->InterruptObject != NULL) ! 803: IoDisconnectInterrupt(deviceExtension->InterruptObject); ! 804: if (deviceExtension->Configuration.UnmapRegistersRequired) { ! 805: ! 806: MmUnmapIoSpace( ! 807: deviceExtension->Configuration.DeviceRegisters[0], ! 808: deviceExtension->Configuration.PortList[0].u.Port.Length ! 809: ); ! 810: } ! 811: if (deviceExtension->InputData) ! 812: ExFreePool(deviceExtension->InputData); ! 813: } ! 814: if (portDeviceObject) ! 815: IoDeleteDevice(portDeviceObject); ! 816: } ! 817: ! 818: // ! 819: // Free the resource list. ! 820: // ! 821: // N.B. If we ever decide to hang on to the resource list instead, ! 822: // we need to allocate it from non-paged pool (it is now paged pool). ! 823: // ! 824: ! 825: if (resources) ! 826: ExFreePool(resources); ! 827: ! 828: // ! 829: // Free the unicode strings. ! 830: // ! 831: ! 832: if (deviceNameSuffix.MaximumLength != 0) ! 833: ExFreePool(deviceNameSuffix.Buffer); ! 834: if (fullDeviceName.MaximumLength != 0) ! 835: ExFreePool(fullDeviceName.Buffer); ! 836: if (registryPath.MaximumLength != 0) ! 837: ExFreePool(registryPath.Buffer); ! 838: ! 839: ! 840: SerMouPrint((1,"SERMOUSE-SerialMouseInitialize: exit\n")); ! 841: ! 842: return(status); ! 843: ! 844: } ! 845: ! 846: ! 847: VOID ! 848: SerialMouseUnload( ! 849: IN PDRIVER_OBJECT DriverObject ! 850: ) ! 851: { ! 852: UNREFERENCED_PARAMETER(DriverObject); ! 853: ! 854: SerMouPrint((2, "SERMOUSE-SerialMouseUnload: enter\n")); ! 855: SerMouPrint((2, "SERMOUSE-SerialMouseUnload: exit\n")); ! 856: } ! 857: ! 858: VOID ! 859: SerMouBuildResourceList( ! 860: IN PDEVICE_EXTENSION DeviceExtension, ! 861: OUT PCM_RESOURCE_LIST *ResourceList, ! 862: OUT PULONG ResourceListSize ! 863: ) ! 864: ! 865: /*++ ! 866: ! 867: Routine Description: ! 868: ! 869: Creates a resource list that is used to query or report resource usage. ! 870: ! 871: Arguments: ! 872: ! 873: DeviceExtension - Pointer to the port's device extension. ! 874: ! 875: ResourceList - Pointer to a pointer to the resource list to be allocated ! 876: and filled. ! 877: ! 878: ResourceListSize - Pointer to the returned size of the resource ! 879: list (in bytes). ! 880: ! 881: Return Value: ! 882: ! 883: None. If the call succeeded, *ResourceList points to the built ! 884: resource list and *ResourceListSize is set to the size (in bytes) ! 885: of the resource list; otherwise, *ResourceList is NULL. ! 886: ! 887: Note: ! 888: ! 889: Memory is allocated here for *ResourceList. It must be ! 890: freed up by the caller, by calling ExFreePool(); ! 891: ! 892: --*/ ! 893: ! 894: { ! 895: ULONG count = 0; ! 896: PIO_ERROR_LOG_PACKET errorLogEntry; ! 897: ULONG i = 0; ! 898: ULONG j = 0; ! 899: ! 900: count += DeviceExtension->Configuration.PortListCount; ! 901: if (DeviceExtension->Configuration.MouseInterrupt.Type ! 902: == CmResourceTypeInterrupt) ! 903: count += 1; ! 904: ! 905: *ResourceListSize = sizeof(CM_RESOURCE_LIST) + ! 906: ((count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); ! 907: ! 908: *ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool( ! 909: PagedPool, ! 910: *ResourceListSize ! 911: ); ! 912: ! 913: // ! 914: // Return NULL if the structure could not be allocated. ! 915: // Otherwise, fill in the resource list. ! 916: // ! 917: ! 918: if (!*ResourceList) { ! 919: ! 920: // ! 921: // Could not allocate memory for the resource list. ! 922: // ! 923: ! 924: SerMouPrint(( ! 925: 1, ! 926: "SERMOUSE-SerMouBuildResourceList: Could not allocate resource list\n" ! 927: )); ! 928: ! 929: // ! 930: // Log an error. ! 931: // ! 932: ! 933: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( ! 934: DeviceExtension->DeviceObject, ! 935: sizeof(IO_ERROR_LOG_PACKET) ! 936: + sizeof(ULONG) ! 937: ); ! 938: ! 939: if (errorLogEntry != NULL) { ! 940: ! 941: errorLogEntry->ErrorCode = SERMOUSE_INSUFFICIENT_RESOURCES; ! 942: errorLogEntry->DumpDataSize = sizeof(ULONG); ! 943: errorLogEntry->SequenceNumber = 0; ! 944: errorLogEntry->MajorFunctionCode = 0; ! 945: errorLogEntry->IoControlCode = 0; ! 946: errorLogEntry->RetryCount = 0; ! 947: errorLogEntry->UniqueErrorValue = ! 948: SERIAL_MOUSE_ERROR_VALUE_BASE + 110; ! 949: errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES; ! 950: errorLogEntry->DumpData[0] = *ResourceListSize; ! 951: *ResourceListSize = 0; ! 952: ! 953: IoWriteErrorLogEntry(errorLogEntry); ! 954: } ! 955: ! 956: return; ! 957: ! 958: } ! 959: ! 960: RtlZeroMemory( ! 961: *ResourceList, ! 962: *ResourceListSize ! 963: ); ! 964: ! 965: // ! 966: // Concoct one full resource descriptor. ! 967: // ! 968: ! 969: (*ResourceList)->Count = 1; ! 970: ! 971: (*ResourceList)->List[0].InterfaceType = ! 972: DeviceExtension->Configuration.InterfaceType; ! 973: (*ResourceList)->List[0].BusNumber = ! 974: DeviceExtension->Configuration.BusNumber; ! 975: ! 976: // ! 977: // Build the partial resource descriptors for interrupt and port ! 978: // resources from the saved values. ! 979: // ! 980: ! 981: (*ResourceList)->List[0].PartialResourceList.Count = count; ! 982: if (DeviceExtension->Configuration.MouseInterrupt.Type ! 983: == CmResourceTypeInterrupt) ! 984: (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] = ! 985: DeviceExtension->Configuration.MouseInterrupt; ! 986: ! 987: for (j = 0; j < DeviceExtension->Configuration.PortListCount; j++) { ! 988: (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] = ! 989: DeviceExtension->Configuration.PortList[j]; ! 990: } ! 991: ! 992: } ! 993: ! 994: VOID ! 995: SerMouConfiguration( ! 996: IN PDEVICE_EXTENSION DeviceExtension, ! 997: IN PUNICODE_STRING RegistryPath, ! 998: IN PUNICODE_STRING DeviceName ! 999: ) ! 1000: ! 1001: /*++ ! 1002: ! 1003: Routine Description: ! 1004: ! 1005: This routine retrieves the configuration information for the mouse. ! 1006: ! 1007: Arguments: ! 1008: ! 1009: DeviceExtension - Pointer to the device extension. ! 1010: ! 1011: RegistryPath - Pointer to the null-terminated Unicode name of the ! 1012: registry path for this driver. ! 1013: ! 1014: DeviceName - Pointer to the Unicode string that will receive ! 1015: the port device name. ! 1016: ! 1017: Return Value: ! 1018: ! 1019: None. As a side-effect, may set DeviceExtension->HardwarePresent. ! 1020: ! 1021: --*/ ! 1022: { ! 1023: NTSTATUS status = STATUS_SUCCESS; ! 1024: INTERFACE_TYPE interfaceType; ! 1025: CONFIGURATION_TYPE controllerType = SerialController; ! 1026: CONFIGURATION_TYPE peripheralType = PointerPeripheral; ! 1027: ULONG i; ! 1028: ! 1029: for (i=0; ! 1030: i < MaximumInterfaceType && !DeviceExtension->HardwarePresent; ! 1031: i++) { ! 1032: ! 1033: // ! 1034: // Get the hardware registry information for this device. ! 1035: // ! 1036: ! 1037: interfaceType = i; ! 1038: ! 1039: status = IoQueryDeviceDescription(&interfaceType, ! 1040: NULL, ! 1041: &controllerType, ! 1042: NULL, ! 1043: &peripheralType, ! 1044: NULL, ! 1045: SerMouPeripheralCallout, ! 1046: (PVOID) DeviceExtension); ! 1047: ! 1048: if (!DeviceExtension->HardwarePresent) { ! 1049: SerMouPrint(( ! 1050: 1, ! 1051: "SERMOUSE-SerMouConfiguration: IoQueryDeviceDescription for PointerPeripheral on bus type %d failed\n", ! 1052: interfaceType ! 1053: )); ! 1054: } ! 1055: } ! 1056: ! 1057: // ! 1058: // Get the driver's service parameters from the registry (e.g., ! 1059: // user-configurable data input queue size, etc.). Note that the ! 1060: // service parameters can override information from the hardware ! 1061: // registry (e.g., the service parameters can specify that ! 1062: // the hardware is on the system, regardless of what the ! 1063: // detection logic recognized). ! 1064: // ! 1065: ! 1066: SerMouServiceParameters( ! 1067: DeviceExtension, ! 1068: RegistryPath, ! 1069: DeviceName ! 1070: ); ! 1071: ! 1072: if ((!DeviceExtension->HardwarePresent) && ! 1073: (DeviceExtension->Configuration.OverrideHardwarePresent ! 1074: != DEFAULT_OVERRIDE_HARDWARE)) { ! 1075: ! 1076: // ! 1077: // There was no information about a pointer peripheral on a ! 1078: // serial controller in the hardware registry, but the driver's ! 1079: // service parameters specify that we should assume there is ! 1080: // a serial mouse on the system anyway. Attempt to find the ! 1081: // hardware registry information for the serial port specified ! 1082: // in the override portion of the driver service parameters. ! 1083: // ! 1084: ! 1085: for (i=0; ! 1086: i < MaximumInterfaceType && !DeviceExtension->HardwarePresent; ! 1087: i++) { ! 1088: ! 1089: ULONG peripheralNumber = ! 1090: DeviceExtension->Configuration.OverrideHardwarePresent - 1; ! 1091: ! 1092: // ! 1093: // Get the hardware registry information for the serial ! 1094: // peripheral specified as the "override". ! 1095: // ! 1096: ! 1097: interfaceType = i; ! 1098: ! 1099: status = IoQueryDeviceDescription( ! 1100: &interfaceType, ! 1101: NULL, ! 1102: &controllerType, ! 1103: NULL, ! 1104: NULL, ! 1105: &peripheralNumber, ! 1106: SerMouPeripheralCallout, ! 1107: (PVOID) DeviceExtension ! 1108: ); ! 1109: ! 1110: if (!DeviceExtension->HardwarePresent) { ! 1111: SerMouPrint(( ! 1112: 1, ! 1113: "SERMOUSE-SerMouConfiguration: IoQueryDeviceDescription for SerialPeripheral on bus type %d failed\n", ! 1114: interfaceType ! 1115: )); ! 1116: } ! 1117: } ! 1118: ! 1119: DeviceExtension->HardwarePresent = MOUSE_HARDWARE_PRESENT; ! 1120: } ! 1121: ! 1122: if (DeviceExtension->HardwarePresent) { ! 1123: ! 1124: // ! 1125: // Initialize mouse-specific configuration parameters. ! 1126: // ! 1127: ! 1128: DeviceExtension->Configuration.MouseAttributes.MouseIdentifier = ! 1129: MOUSE_SERIAL_HARDWARE; ! 1130: } ! 1131: } ! 1132: ! 1133: VOID ! 1134: SerMouDisableInterrupts( ! 1135: IN PVOID Context ! 1136: ) ! 1137: ! 1138: /*++ ! 1139: ! 1140: Routine Description: ! 1141: ! 1142: This routine is called from StartIo synchronously. It touches the ! 1143: hardware to disable interrupts. ! 1144: ! 1145: Arguments: ! 1146: ! 1147: Context - Pointer to the device extension. ! 1148: ! 1149: Return Value: ! 1150: ! 1151: None. ! 1152: ! 1153: --*/ ! 1154: ! 1155: { ! 1156: PUCHAR port; ! 1157: PLONG enableCount; ! 1158: UCHAR mask; ! 1159: ! 1160: // ! 1161: // Decrement the reference count for device enables. ! 1162: // ! 1163: ! 1164: enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount; ! 1165: *enableCount = *enableCount - 1; ! 1166: ! 1167: if (*enableCount == 0) { ! 1168: ! 1169: // ! 1170: // Get the port register address. ! 1171: // ! 1172: ! 1173: port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0]; ! 1174: ! 1175: // ! 1176: // Disable hardware interrupts. ! 1177: // ! 1178: ! 1179: WRITE_PORT_UCHAR((PUCHAR) (port + ACE_IER), 0); ! 1180: ! 1181: // ! 1182: // Turn off modem control output line 2. ! 1183: // ! 1184: ! 1185: mask = READ_PORT_UCHAR((PUCHAR) (port + ACE_MCR)); ! 1186: WRITE_PORT_UCHAR((PUCHAR) (port + ACE_MCR), (UCHAR)(mask & ~ACE_OUT2)); ! 1187: } ! 1188: } ! 1189: ! 1190: VOID ! 1191: SerMouEnableInterrupts( ! 1192: IN PVOID Context ! 1193: ) ! 1194: ! 1195: /*++ ! 1196: ! 1197: Routine Description: ! 1198: ! 1199: This routine is called from StartIo synchronously. It touches the ! 1200: hardware to enable interrupts. ! 1201: ! 1202: Arguments: ! 1203: ! 1204: Context - Pointer to the device extension. ! 1205: ! 1206: Return Value: ! 1207: ! 1208: None. ! 1209: ! 1210: --*/ ! 1211: ! 1212: { ! 1213: PUCHAR port; ! 1214: PLONG enableCount; ! 1215: UCHAR mask; ! 1216: ! 1217: ! 1218: enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount; ! 1219: ! 1220: if (*enableCount == 0) { ! 1221: ! 1222: // ! 1223: // Get the port register address. ! 1224: // ! 1225: ! 1226: port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0]; ! 1227: ! 1228: // ! 1229: // Enable the serial mouse's interrupt at the i8250. ! 1230: // ! 1231: ! 1232: WRITE_PORT_UCHAR((PUCHAR) (port + ACE_IER), ACE_ERBFI); ! 1233: ! 1234: // ! 1235: // Turn on modem control output line 2. ! 1236: // ! 1237: ! 1238: mask = READ_PORT_UCHAR((PUCHAR) (port + ACE_MCR)); ! 1239: WRITE_PORT_UCHAR((PUCHAR) (port + ACE_MCR), (UCHAR)(mask | ACE_OUT2)); ! 1240: ! 1241: // ! 1242: // Clean possible garbage in uart input buffer. ! 1243: // ! 1244: ! 1245: UARTFlushReadBuffer(port); ! 1246: } ! 1247: ! 1248: // ! 1249: // Increment the reference count for device enables. ! 1250: // ! 1251: ! 1252: *enableCount = *enableCount + 1; ! 1253: } ! 1254: ! 1255: NTSTATUS ! 1256: SerMouInitializeHardware( ! 1257: IN PDEVICE_OBJECT DeviceObject ! 1258: ) ! 1259: ! 1260: /*++ ! 1261: ! 1262: Routine Description: ! 1263: ! 1264: This routine initializes the serial mouse/ballpoint. Note that this ! 1265: routine is only called at initialization time, so synchronization is ! 1266: not required. ! 1267: ! 1268: Arguments: ! 1269: ! 1270: DeviceObject - Pointer to the device object. ! 1271: ! 1272: Return Value: ! 1273: ! 1274: STATUS_SUCCESS if a pointing device is detected, otherwise STATUS_UNSUCCESSFUL ! 1275: ! 1276: --*/ ! 1277: ! 1278: { ! 1279: PDEVICE_EXTENSION deviceExtension; ! 1280: PUCHAR port; ! 1281: UCHAR mask; ! 1282: UCHAR byte; ! 1283: ULONG i; ! 1284: MOUSETYPE mouseType; ! 1285: ULONG hardwareButtons; ! 1286: NTSTATUS status = STATUS_UNSUCCESSFUL; ! 1287: ! 1288: SerMouPrint((2, "SERMOUSE-SerMouInitializeHardware: enter\n")); ! 1289: ! 1290: // ! 1291: // Grab useful configuration parameters from the device extension. ! 1292: // ! 1293: ! 1294: deviceExtension = DeviceObject->DeviceExtension; ! 1295: port = deviceExtension->Configuration.DeviceRegisters[0]; ! 1296: ! 1297: // ! 1298: // Save the UART initial state. ! 1299: // ! 1300: ! 1301: SerMouPrint ! 1302: (( ! 1303: 2, ! 1304: "SERMOUSE-SerMouInitializeHardware: Saving UART state\n" ! 1305: )); ! 1306: ! 1307: UARTGetState( ! 1308: port, ! 1309: &deviceExtension->Configuration.UartSaved, ! 1310: deviceExtension->Configuration.BaudClock ! 1311: ); ! 1312: ! 1313: // ! 1314: // Disable interrupts at the i8250. ! 1315: // ! 1316: ! 1317: SerMouPrint ! 1318: (( ! 1319: 2, ! 1320: "SERMOUSE-SerMouInitializeHardware: Disabling UART interrupts\n" ! 1321: )); ! 1322: ! 1323: UARTSetInterruptCtrl(port, 0); ! 1324: ! 1325: ! 1326: SerMouPrint ! 1327: (( ! 1328: 2, ! 1329: "SERMOUSE-SerMouInitializeHardware: Setting UART line control\n" ! 1330: )); ! 1331: ! 1332: if ((mouseType = MSerDetect(port, deviceExtension->Configuration.BaudClock)) ! 1333: != NO_MOUSE) { ! 1334: status = STATUS_SUCCESS; ! 1335: switch (mouseType) { ! 1336: case MOUSE_2B: ! 1337: deviceExtension->ProtocolHandler = ! 1338: MSerSetProtocol(port, MSER_PROTOCOL_MP); ! 1339: hardwareButtons = 2; ! 1340: break; ! 1341: case MOUSE_3B: ! 1342: deviceExtension->ProtocolHandler = ! 1343: MSerSetProtocol(port, MSER_PROTOCOL_MP); ! 1344: hardwareButtons = 3; ! 1345: break; ! 1346: case BALLPOINT: ! 1347: deviceExtension->ProtocolHandler = ! 1348: MSerSetProtocol(port, MSER_PROTOCOL_BP); ! 1349: hardwareButtons = 2; ! 1350: break; ! 1351: } ! 1352: } ! 1353: else if (CSerDetect(port, deviceExtension->Configuration.BaudClock)) { ! 1354: status = STATUS_SUCCESS; ! 1355: deviceExtension->ProtocolHandler = ! 1356: CSerSetProtocol(port, CSER_PROTOCOL_MM); ! 1357: hardwareButtons = 2; ! 1358: } ! 1359: else { ! 1360: deviceExtension->ProtocolHandler = NULL; ! 1361: hardwareButtons = MOUSE_NUMBER_OF_BUTTONS; ! 1362: } ! 1363: ! 1364: ! 1365: // ! 1366: // If the hardware wasn't overridden, set the number of buttons ! 1367: // according to the protocol. ! 1368: // ! 1369: ! 1370: if (deviceExtension->Configuration.OverrideHardwarePresent == DEFAULT_OVERRIDE_HARDWARE) { ! 1371: ! 1372: deviceExtension->Configuration.MouseAttributes.NumberOfButtons = ! 1373: hardwareButtons; ! 1374: ! 1375: } ! 1376: ! 1377: if (NT_SUCCESS(status)) { ! 1378: ! 1379: // ! 1380: // Make sure the FIFO is turned off. ! 1381: // ! 1382: ! 1383: UARTSetFifo(port, 0); ! 1384: ! 1385: // ! 1386: // Clean up anything left in the receive buffer. ! 1387: // ! 1388: ! 1389: UARTFlushReadBuffer(port); ! 1390: ! 1391: } ! 1392: else { ! 1393: ! 1394: // ! 1395: // Restore the hardware to its previous state. ! 1396: // ! 1397: ! 1398: UARTSetState( ! 1399: port, ! 1400: &deviceExtension->Configuration.UartSaved, ! 1401: deviceExtension->Configuration.BaudClock ! 1402: ); ! 1403: } ! 1404: ! 1405: SerMouPrint((2, "SERMOUSE-SerMouInitializeHardware: exit\n")); ! 1406: ! 1407: return status; ! 1408: ! 1409: } ! 1410: ! 1411: NTSTATUS ! 1412: SerMouPeripheralCallout( ! 1413: IN PVOID Context, ! 1414: IN PUNICODE_STRING PathName, ! 1415: IN INTERFACE_TYPE BusType, ! 1416: IN ULONG BusNumber, ! 1417: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 1418: IN CONFIGURATION_TYPE ControllerType, ! 1419: IN ULONG ControllerNumber, ! 1420: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 1421: IN CONFIGURATION_TYPE PeripheralType, ! 1422: IN ULONG PeripheralNumber, ! 1423: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 1424: ) ! 1425: ! 1426: /*++ ! 1427: ! 1428: Routine Description: ! 1429: ! 1430: This is the callout routine sent as a parameter to ! 1431: IoQueryDeviceDescription. It grabs the pointer controller and ! 1432: peripheral configuration information. ! 1433: ! 1434: Arguments: ! 1435: ! 1436: Context - Context parameter that was passed in by the routine ! 1437: that called IoQueryDeviceDescription. ! 1438: ! 1439: PathName - The full pathname for the registry key. ! 1440: ! 1441: BusType - Bus interface type (Isa, Eisa, Mca, etc.). ! 1442: ! 1443: BusNumber - The bus sub-key (0, 1, etc.). ! 1444: ! 1445: BusInformation - Pointer to the array of pointers to the full value ! 1446: information for the bus. ! 1447: ! 1448: ControllerType - The controller type (should be SerialController). ! 1449: ! 1450: ControllerNumber - The controller sub-key (0, 1, etc.). ! 1451: ! 1452: ControllerInformation - Pointer to the array of pointers to the full ! 1453: value information for the controller key. ! 1454: ! 1455: PeripheralType - The peripheral type (should be PointerPeripheral). ! 1456: ! 1457: PeripheralNumber - The peripheral sub-key. ! 1458: ! 1459: PeripheralInformation - Pointer to the array of pointers to the full ! 1460: value information for the peripheral key. ! 1461: ! 1462: ! 1463: Return Value: ! 1464: ! 1465: None. If successful, will have the following side-effects: ! 1466: ! 1467: - Sets DeviceObject->DeviceExtension->HardwarePresent. ! 1468: - Sets configuration fields in ! 1469: DeviceObject->DeviceExtension->Configuration. ! 1470: ! 1471: --*/ ! 1472: { ! 1473: PDEVICE_EXTENSION deviceExtension; ! 1474: PSERIAL_MOUSE_CONFIGURATION_INFORMATION configuration; ! 1475: UNICODE_STRING unicodeIdentifier; ! 1476: PUCHAR controllerData; ! 1477: NTSTATUS status = STATUS_SUCCESS; ! 1478: ULONG i; ! 1479: ULONG listCount; ! 1480: PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor; ! 1481: PCM_SERIAL_DEVICE_DATA serialSpecificData; ! 1482: ANSI_STRING ansiString; ! 1483: BOOLEAN defaultInterruptShare; ! 1484: KINTERRUPT_MODE defaultInterruptMode; ! 1485: ! 1486: SerMouPrint(( ! 1487: 1, ! 1488: "SERMOUSE-SerMouPeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n", ! 1489: PathName, BusType, BusNumber ! 1490: )); ! 1491: SerMouPrint(( ! 1492: 1, ! 1493: " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n", ! 1494: ControllerType, ControllerNumber, ControllerInformation ! 1495: )); ! 1496: SerMouPrint(( ! 1497: 1, ! 1498: " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n", ! 1499: PeripheralType, PeripheralNumber, PeripheralInformation ! 1500: )); ! 1501: ! 1502: // ! 1503: // If we already have the configuration information for the ! 1504: // mouse peripheral, just return. ! 1505: // ! 1506: ! 1507: deviceExtension = (PDEVICE_EXTENSION) Context; ! 1508: if (deviceExtension->HardwarePresent) { ! 1509: ! 1510: // ! 1511: // Future: Change driver to handle multiple port devices ! 1512: // (create multiple port device objects). ! 1513: // ! 1514: ! 1515: return ( status ); ! 1516: } ! 1517: ! 1518: configuration = &deviceExtension->Configuration; ! 1519: ! 1520: // ! 1521: // If OverrideHardwarePresent is zero, this routine was called ! 1522: // as a result of the IoQueryDeviceDescription for serial ! 1523: // PointerPeripheral information. Otherwise, it was called as ! 1524: // a result of the IoQueryDeviceDescription for generic ! 1525: // serial controller information. In the latter case, the ! 1526: // mouse-specific code is skipped. ! 1527: // ! 1528: ! 1529: if (configuration->OverrideHardwarePresent == 0) { ! 1530: ! 1531: // ! 1532: // Get the identifier information for the peripheral. If ! 1533: // the peripheral identifier is missing, just return. ! 1534: // ! 1535: ! 1536: unicodeIdentifier.Length = ! 1537: (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength; ! 1538: if (unicodeIdentifier.Length == 0) { ! 1539: return(status); ! 1540: } ! 1541: ! 1542: unicodeIdentifier.MaximumLength = unicodeIdentifier.Length; ! 1543: unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation + ! 1544: IoQueryDeviceIdentifier))) + ! 1545: (*(PeripheralInformation + ! 1546: IoQueryDeviceIdentifier))->DataOffset); ! 1547: SerMouPrint(( ! 1548: 1, ! 1549: "SERMOUSE-SerMouPeripheralCallout: Mouse type %ws\n", ! 1550: unicodeIdentifier.Buffer ! 1551: )); ! 1552: ! 1553: // ! 1554: // Verify that this is a serial mouse or ballpoint. ! 1555: // ! 1556: ! 1557: status = RtlUnicodeStringToAnsiString( ! 1558: &ansiString, ! 1559: &unicodeIdentifier, ! 1560: TRUE ! 1561: ); ! 1562: ! 1563: if (!NT_SUCCESS(status)) { ! 1564: SerMouPrint(( ! 1565: 1, ! 1566: "SERMOUSE-SerMouPeripheralCallout: Could not convert identifier to Ansi\n" ! 1567: )); ! 1568: return(status); ! 1569: } ! 1570: ! 1571: if (strstr(ansiString.Buffer, "SERIAL MOUSE")) { ! 1572: ! 1573: // ! 1574: // There is a serial mouse/ballpoint. ! 1575: // ! 1576: ! 1577: deviceExtension->HardwarePresent = MOUSE_HARDWARE_PRESENT; ! 1578: ! 1579: } ! 1580: ! 1581: RtlFreeAnsiString(&ansiString); ! 1582: } else { ! 1583: ! 1584: // ! 1585: // Go ahead and assume, because of the service parameter override, ! 1586: // that there is serial mouse on this serial controller. ! 1587: // ! 1588: ! 1589: if ((ULONG)(configuration->OverrideHardwarePresent - 1) == ControllerNumber) { ! 1590: deviceExtension->HardwarePresent = MOUSE_HARDWARE_PRESENT; ! 1591: } ! 1592: } ! 1593: ! 1594: if (!deviceExtension->HardwarePresent) ! 1595: return(status); ! 1596: ! 1597: // ! 1598: // Get the bus information. ! 1599: // ! 1600: ! 1601: configuration->InterfaceType = BusType; ! 1602: configuration->BusNumber = BusNumber; ! 1603: configuration->FloatingSave = SERIAL_MOUSE_FLOATING_SAVE; ! 1604: ! 1605: if (BusType == MicroChannel) { ! 1606: defaultInterruptShare = TRUE; ! 1607: defaultInterruptMode = LevelSensitive; ! 1608: } else { ! 1609: defaultInterruptShare = SERIAL_MOUSE_INTERRUPT_SHARE; ! 1610: defaultInterruptMode = SERIAL_MOUSE_INTERRUPT_MODE; ! 1611: } ! 1612: ! 1613: // ! 1614: // Look through the resource list for interrupt and port ! 1615: // configuration information. ! 1616: // ! 1617: ! 1618: if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){ ! 1619: controllerData = ((PUCHAR) (*(ControllerInformation + ! 1620: IoQueryDeviceConfigurationData))) + ! 1621: (*(ControllerInformation + ! 1622: IoQueryDeviceConfigurationData))->DataOffset; ! 1623: ! 1624: controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, ! 1625: PartialResourceList); ! 1626: ! 1627: listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count; ! 1628: ! 1629: resourceDescriptor = ! 1630: ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors; ! 1631: ! 1632: for (i = 0; i < listCount; i++, resourceDescriptor++) { ! 1633: switch(resourceDescriptor->Type) { ! 1634: case CmResourceTypePort: ! 1635: ! 1636: // ! 1637: // Copy the port information. Note that we only expect to ! 1638: // find one port range for the serial mouse/ballpoint. ! 1639: // ! 1640: ! 1641: configuration->PortListCount = 0; ! 1642: configuration->PortList[configuration->PortListCount] = ! 1643: *resourceDescriptor; ! 1644: configuration->PortList[configuration->PortListCount].ShareDisposition = ! 1645: SERIAL_MOUSE_REGISTER_SHARE? CmResourceShareShared: ! 1646: CmResourceShareDeviceExclusive; ! 1647: configuration->PortListCount += 1; ! 1648: ! 1649: break; ! 1650: ! 1651: case CmResourceTypeInterrupt: ! 1652: ! 1653: // ! 1654: // Copy the interrupt information. ! 1655: // ! 1656: ! 1657: configuration->MouseInterrupt = *resourceDescriptor; ! 1658: configuration->MouseInterrupt.ShareDisposition = ! 1659: defaultInterruptShare? CmResourceShareShared : ! 1660: CmResourceShareDeviceExclusive; ! 1661: ! 1662: break; ! 1663: ! 1664: case CmResourceTypeDeviceSpecific: ! 1665: ! 1666: // ! 1667: // Get the clock rate. This is used to determine the ! 1668: // divisor for setting the serial baud rate. ! 1669: // ! 1670: ! 1671: serialSpecificData = ! 1672: (PCM_SERIAL_DEVICE_DATA) (((PUCHAR) resourceDescriptor) ! 1673: + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); ! 1674: configuration->BaudClock = ! 1675: serialSpecificData->BaudClock; ! 1676: break; ! 1677: ! 1678: default: ! 1679: break; ! 1680: } ! 1681: } ! 1682: } ! 1683: ! 1684: // ! 1685: // If no interrupt configuration information was found, use the ! 1686: // driver defaults. ! 1687: // ! 1688: ! 1689: if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) { ! 1690: ! 1691: SerMouPrint(( ! 1692: 1, ! 1693: "SERMOUSE-SerMouPeripheralCallout: Using default mouse interrupt config\n" ! 1694: )); ! 1695: ! 1696: configuration->MouseInterrupt.Type = CmResourceTypeInterrupt; ! 1697: configuration->MouseInterrupt.ShareDisposition = ! 1698: defaultInterruptShare? CmResourceShareShared : ! 1699: CmResourceShareDeviceExclusive; ! 1700: configuration->MouseInterrupt.Flags = ! 1701: (defaultInterruptMode == Latched)? ! 1702: CM_RESOURCE_INTERRUPT_LATCHED : ! 1703: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 1704: configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL; ! 1705: configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR; ! 1706: } ! 1707: ! 1708: SerMouPrint(( ! 1709: 1, ! 1710: "SERMOUSE-SerMouPeripheralCallout: Mouse config --\n" ! 1711: )); ! 1712: SerMouPrint(( ! 1713: 1, ! 1714: "\t%s, %s, Irq = %d\n", ! 1715: configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared? ! 1716: "Sharable" : "NonSharable", ! 1717: configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED? ! 1718: "Latched" : "Level Sensitive", ! 1719: configuration->MouseInterrupt.u.Interrupt.Vector ! 1720: )); ! 1721: ! 1722: // ! 1723: // If no port configuration information was found, use the ! 1724: // driver defaults. ! 1725: // ! 1726: ! 1727: if (configuration->PortListCount == 0) { ! 1728: ! 1729: // ! 1730: // No port configuration information was found, so use ! 1731: // the driver defaults. ! 1732: // ! 1733: ! 1734: SerMouPrint(( ! 1735: 1, ! 1736: "SERMOUSE-SerMouPeripheralCallout: Using default port config\n" ! 1737: )); ! 1738: ! 1739: configuration->PortList[0].Type = CmResourceTypePort; ! 1740: configuration->PortList[0].Flags = SERIAL_MOUSE_PORT_TYPE; ! 1741: configuration->PortList[0].ShareDisposition = ! 1742: SERIAL_MOUSE_REGISTER_SHARE? CmResourceShareShared: ! 1743: CmResourceShareDeviceExclusive; ! 1744: configuration->PortList[0].u.Port.Start.LowPart = ! 1745: SERIAL_MOUSE_PHYSICAL_BASE; ! 1746: configuration->PortList[0].u.Port.Start.HighPart = 0; ! 1747: configuration->PortList[0].u.Port.Length = ! 1748: SERIAL_MOUSE_REGISTER_LENGTH; ! 1749: ! 1750: configuration->PortListCount = 1; ! 1751: } ! 1752: ! 1753: for (i = 0; i < configuration->PortListCount; i++) { ! 1754: ! 1755: SerMouPrint(( ! 1756: 1, ! 1757: "\t%s, Ports 0x%x - 0x%x\n", ! 1758: configuration->PortList[i].ShareDisposition ! 1759: == CmResourceShareShared? "Sharable" : "NonSharable", ! 1760: configuration->PortList[i].u.Port.Start.LowPart, ! 1761: configuration->PortList[i].u.Port.Start.LowPart + ! 1762: configuration->PortList[i].u.Port.Length - 1 ! 1763: )); ! 1764: } ! 1765: ! 1766: // ! 1767: // If no baud clock information was found, use the driver defaults. ! 1768: // ! 1769: ! 1770: if (configuration->BaudClock == 0) { ! 1771: configuration->BaudClock = MOUSE_BAUD_CLOCK; ! 1772: } ! 1773: ! 1774: SerMouPrint(( ! 1775: 1, ! 1776: "\tBaud clock %ld Hz\n", ! 1777: configuration->BaudClock ! 1778: )); ! 1779: ! 1780: return( status ); ! 1781: } ! 1782: ! 1783: VOID ! 1784: SerMouServiceParameters( ! 1785: IN PDEVICE_EXTENSION DeviceExtension, ! 1786: IN PUNICODE_STRING RegistryPath, ! 1787: IN PUNICODE_STRING DeviceName ! 1788: ) ! 1789: ! 1790: /*++ ! 1791: ! 1792: Routine Description: ! 1793: ! 1794: This routine retrieves this driver's service parameters information ! 1795: from the registry. ! 1796: ! 1797: Arguments: ! 1798: ! 1799: DeviceExtension - Pointer to the device extension. ! 1800: ! 1801: RegistryPath - Pointer to the null-terminated Unicode name of the ! 1802: registry path for this driver. ! 1803: ! 1804: DeviceName - Pointer to the Unicode string that will receive ! 1805: the port device name. ! 1806: ! 1807: Return Value: ! 1808: ! 1809: None. As a side-effect, sets fields in DeviceExtension->Configuration. ! 1810: ! 1811: --*/ ! 1812: ! 1813: { ! 1814: PSERIAL_MOUSE_CONFIGURATION_INFORMATION configuration; ! 1815: PRTL_QUERY_REGISTRY_TABLE parameters = NULL; ! 1816: UNICODE_STRING parametersPath; ! 1817: ULONG defaultDataQueueSize = DATA_QUEUE_SIZE; ! 1818: ULONG numberOfButtons = MOUSE_NUMBER_OF_BUTTONS; ! 1819: USHORT defaultNumberOfButtons = MOUSE_NUMBER_OF_BUTTONS; ! 1820: ULONG sampleRate = MOUSE_SAMPLE_RATE; ! 1821: USHORT defaultSampleRate = MOUSE_SAMPLE_RATE; ! 1822: UNICODE_STRING defaultUnicodeName; ! 1823: LONG defaultHardwarePresent = DEFAULT_OVERRIDE_HARDWARE; ! 1824: NTSTATUS status = STATUS_SUCCESS; ! 1825: PWSTR path = NULL; ! 1826: ULONG overrideBits, comPort, i; ! 1827: USHORT queriesPlusOne = 6; ! 1828: BOOLEAN defaultInterruptShare; ! 1829: KINTERRUPT_MODE defaultInterruptMode; ! 1830: ! 1831: configuration = &DeviceExtension->Configuration; ! 1832: parametersPath.Buffer = NULL; ! 1833: ! 1834: // ! 1835: // Registry path is already null-terminated, so just use it. ! 1836: // ! 1837: ! 1838: path = RegistryPath->Buffer; ! 1839: ! 1840: if (NT_SUCCESS(status)) { ! 1841: ! 1842: // ! 1843: // Allocate the Rtl query table. ! 1844: // ! 1845: ! 1846: parameters = ExAllocatePool( ! 1847: PagedPool, ! 1848: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne ! 1849: ); ! 1850: ! 1851: if (!parameters) { ! 1852: ! 1853: SerMouPrint(( ! 1854: 1, ! 1855: "SERMOUSE-SerMouServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n", ! 1856: path ! 1857: )); ! 1858: ! 1859: status = STATUS_UNSUCCESSFUL; ! 1860: ! 1861: } else { ! 1862: ! 1863: RtlZeroMemory( ! 1864: parameters, ! 1865: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne ! 1866: ); ! 1867: ! 1868: // ! 1869: // Form a path to this driver's Parameters subkey. ! 1870: // ! 1871: ! 1872: RtlInitUnicodeString( ! 1873: ¶metersPath, ! 1874: NULL ! 1875: ); ! 1876: ! 1877: parametersPath.MaximumLength = RegistryPath->Length + ! 1878: sizeof(L"\\Parameters"); ! 1879: ! 1880: parametersPath.Buffer = ExAllocatePool( ! 1881: PagedPool, ! 1882: parametersPath.MaximumLength ! 1883: ); ! 1884: ! 1885: if (!parametersPath.Buffer) { ! 1886: ! 1887: SerMouPrint(( ! 1888: 1, ! 1889: "SERMOUSE-SerMouServiceParameters: Couldn't allocate string for path to parameters for %ws\n", ! 1890: path ! 1891: )); ! 1892: ! 1893: status = STATUS_UNSUCCESSFUL; ! 1894: ! 1895: } ! 1896: } ! 1897: } ! 1898: ! 1899: if (NT_SUCCESS(status)) { ! 1900: ! 1901: // ! 1902: // Form the parameters path. ! 1903: // ! 1904: ! 1905: RtlZeroMemory( ! 1906: parametersPath.Buffer, ! 1907: parametersPath.MaximumLength ! 1908: ); ! 1909: RtlAppendUnicodeToString( ! 1910: ¶metersPath, ! 1911: path ! 1912: ); ! 1913: RtlAppendUnicodeToString( ! 1914: ¶metersPath, ! 1915: L"\\Parameters" ! 1916: ); ! 1917: ! 1918: SerMouPrint(( ! 1919: 1, ! 1920: "SERMOUSE-SerMouServiceParameters: parameters path is %ws\n", ! 1921: parametersPath.Buffer ! 1922: )); ! 1923: ! 1924: // ! 1925: // Form the default pointer port device name, in case it is not ! 1926: // specified in the registry. ! 1927: // ! 1928: ! 1929: RtlInitUnicodeString( ! 1930: &defaultUnicodeName, ! 1931: DD_POINTER_PORT_BASE_NAME_U ! 1932: ); ! 1933: ! 1934: // ! 1935: // Gather all of the "user specified" information from ! 1936: // the registry. ! 1937: // ! 1938: ! 1939: parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1940: parameters[0].Name = L"MouseDataQueueSize"; ! 1941: parameters[0].EntryContext = ! 1942: &configuration->MouseAttributes.InputDataQueueLength; ! 1943: parameters[0].DefaultType = REG_DWORD; ! 1944: parameters[0].DefaultData = &defaultDataQueueSize; ! 1945: parameters[0].DefaultLength = sizeof(ULONG); ! 1946: ! 1947: parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1948: parameters[1].Name = L"NumberOfButtons"; ! 1949: parameters[1].EntryContext = &numberOfButtons; ! 1950: parameters[1].DefaultType = REG_DWORD; ! 1951: parameters[1].DefaultData = &defaultNumberOfButtons; ! 1952: parameters[1].DefaultLength = sizeof(USHORT); ! 1953: ! 1954: parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1955: parameters[2].Name = L"SampleRate"; ! 1956: parameters[2].EntryContext = &sampleRate; ! 1957: parameters[2].DefaultType = REG_DWORD; ! 1958: parameters[2].DefaultData = &defaultSampleRate; ! 1959: parameters[2].DefaultLength = sizeof(USHORT); ! 1960: ! 1961: parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1962: parameters[3].Name = L"PointerDeviceBaseName"; ! 1963: parameters[3].EntryContext = DeviceName; ! 1964: parameters[3].DefaultType = REG_SZ; ! 1965: parameters[3].DefaultData = defaultUnicodeName.Buffer; ! 1966: parameters[3].DefaultLength = 0; ! 1967: ! 1968: parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1969: parameters[4].Name = L"OverrideHardwareBitstring"; ! 1970: parameters[4].EntryContext = &configuration->OverrideHardwarePresent; ! 1971: parameters[4].DefaultType = REG_DWORD; ! 1972: parameters[4].DefaultData = &defaultHardwarePresent; ! 1973: parameters[4].DefaultLength = sizeof(LONG); ! 1974: ! 1975: status = RtlQueryRegistryValues( ! 1976: RTL_REGISTRY_ABSOLUTE, ! 1977: parametersPath.Buffer, ! 1978: parameters, ! 1979: NULL, ! 1980: NULL ! 1981: ); ! 1982: ! 1983: } ! 1984: ! 1985: if (!NT_SUCCESS(status)) { ! 1986: ! 1987: SerMouPrint(( ! 1988: 1, ! 1989: "SERMOUSE-SerMouServiceParameters: RtlQueryRegistryValues failed with 0x%x\n", ! 1990: status ! 1991: )); ! 1992: ! 1993: // ! 1994: // Go ahead and assign driver defaults. ! 1995: // ! 1996: ! 1997: configuration->MouseAttributes.InputDataQueueLength = ! 1998: defaultDataQueueSize; ! 1999: configuration->OverrideHardwarePresent = DEFAULT_OVERRIDE_HARDWARE; ! 2000: RtlCopyUnicodeString(DeviceName, &defaultUnicodeName); ! 2001: } ! 2002: ! 2003: // ! 2004: // Check for overrides from the Service Parameters. Allow the ! 2005: // information from the Hardware Registry to be overridden. For ! 2006: // example, the Service Parameters can specify that the hardware ! 2007: // is present on a given COM port, even though the Hardware Registry ! 2008: // indicated otherwise. ! 2009: // ! 2010: ! 2011: if (configuration->OverrideHardwarePresent != defaultHardwarePresent) { ! 2012: if ((!DeviceExtension->HardwarePresent) && (configuration->OverrideHardwarePresent)) { ! 2013: ! 2014: // ! 2015: // Behave as if the hardware is on the system, even though ! 2016: // this conflicts with the Hardware Registry information. Set ! 2017: // the hardware information fields in the device extension to ! 2018: // system defaults depending on which COM port was specified ! 2019: // by the OverrideHardwareBitstring in the registry. Any field ! 2020: // overrides from the Service Parameters will be applied later. ! 2021: // ! 2022: ! 2023: for (overrideBits=configuration->OverrideHardwarePresent,comPort=0; ! 2024: overrideBits != 0; ! 2025: overrideBits >>= 1) { ! 2026: ! 2027: // ! 2028: // Get the desired COM port from the override bitstring. ! 2029: // A 0x1 implies com1, 0x2 implies com2, 0x4 implies com3, ! 2030: // 0x8 implies com4, and so on. ! 2031: // ! 2032: // NOTE: We really only support com1 and com2 today. ! 2033: // ! 2034: ! 2035: comPort += 1; ! 2036: if (overrideBits & 1) { ! 2037: break; ! 2038: } ! 2039: } ! 2040: ! 2041: // ! 2042: // Set the common configuration fields. ! 2043: // ! 2044: ! 2045: configuration->InterfaceType = SERIAL_MOUSE_INTERFACE_TYPE; ! 2046: configuration->BusNumber = SERIAL_MOUSE_BUS_NUMBER; ! 2047: configuration->FloatingSave = SERIAL_MOUSE_FLOATING_SAVE; ! 2048: configuration->MouseInterrupt.Type = CmResourceTypeInterrupt; ! 2049: ! 2050: if (configuration->InterfaceType == MicroChannel) { ! 2051: defaultInterruptShare = TRUE; ! 2052: defaultInterruptMode = LevelSensitive; ! 2053: } else { ! 2054: defaultInterruptShare = SERIAL_MOUSE_INTERRUPT_SHARE; ! 2055: defaultInterruptMode = SERIAL_MOUSE_INTERRUPT_MODE; ! 2056: } ! 2057: ! 2058: configuration->MouseInterrupt.ShareDisposition = ! 2059: defaultInterruptShare? CmResourceShareShared : ! 2060: CmResourceShareDeviceExclusive; ! 2061: configuration->MouseInterrupt.Flags = ! 2062: (defaultInterruptMode == Latched)? ! 2063: CM_RESOURCE_INTERRUPT_LATCHED : ! 2064: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 2065: ! 2066: configuration->PortList[0].Type = CmResourceTypePort; ! 2067: configuration->PortList[0].Flags = SERIAL_MOUSE_PORT_TYPE; ! 2068: configuration->PortList[0].ShareDisposition = ! 2069: SERIAL_MOUSE_REGISTER_SHARE? CmResourceShareShared: ! 2070: CmResourceShareDeviceExclusive; ! 2071: configuration->PortList[0].u.Port.Start.HighPart = 0; ! 2072: configuration->PortList[0].u.Port.Length = ! 2073: SERIAL_MOUSE_REGISTER_LENGTH; ! 2074: ! 2075: configuration->PortListCount = 1; ! 2076: ! 2077: switch (comPort) { ! 2078: case 2: ! 2079: ! 2080: // ! 2081: // Use com2 for the mouse. ! 2082: // ! 2083: ! 2084: configuration->MouseInterrupt.u.Interrupt.Level = ! 2085: MOUSE_COM2_IRQL; ! 2086: configuration->MouseInterrupt.u.Interrupt.Vector = ! 2087: MOUSE_COM2_VECTOR; ! 2088: configuration->PortList[0].u.Port.Start.LowPart = ! 2089: SERIAL_MOUSE_COM2_PHYSICAL_BASE; ! 2090: break; ! 2091: ! 2092: case 1: ! 2093: default: ! 2094: ! 2095: // ! 2096: // Assume com1 for the mouse, unless com2 was specified. ! 2097: // ! 2098: ! 2099: comPort = 1; ! 2100: configuration->MouseInterrupt.u.Interrupt.Level = ! 2101: MOUSE_COM1_IRQL; ! 2102: configuration->MouseInterrupt.u.Interrupt.Vector = ! 2103: MOUSE_COM1_VECTOR; ! 2104: configuration->PortList[0].u.Port.Start.LowPart = ! 2105: SERIAL_MOUSE_COM1_PHYSICAL_BASE; ! 2106: break; ! 2107: } ! 2108: ! 2109: configuration->OverrideHardwarePresent = comPort; ! 2110: ! 2111: SerMouPrint(( ! 2112: 1, ! 2113: "SERMOUSE-SerMouServiceParameters: Overriding hardware registry --\n" ! 2114: )); ! 2115: SerMouPrint(( ! 2116: 1, ! 2117: "SERMOUSE-SerMouServiceParameters: Mouse config --\n" ! 2118: )); ! 2119: SerMouPrint(( ! 2120: 1, ! 2121: "\t%s, %s, Irq = %d\n", ! 2122: configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared? ! 2123: "Sharable" : "NonSharable", ! 2124: configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED? ! 2125: "Latched" : "Level Sensitive", ! 2126: configuration->MouseInterrupt.u.Interrupt.Vector ! 2127: )); ! 2128: ! 2129: for (i = 0; i < configuration->PortListCount; i++) { ! 2130: ! 2131: SerMouPrint(( ! 2132: 1, ! 2133: "\t%s, Ports 0x%x - 0x%x\n", ! 2134: configuration->PortList[i].ShareDisposition ! 2135: == CmResourceShareShared? "Sharable" : "NonSharable", ! 2136: configuration->PortList[i].u.Port.Start.LowPart, ! 2137: configuration->PortList[i].u.Port.Start.LowPart + ! 2138: configuration->PortList[i].u.Port.Length - 1 ! 2139: )); ! 2140: } ! 2141: ! 2142: } ! 2143: ! 2144: } ! 2145: ! 2146: if ((DeviceExtension->HardwarePresent) || ! 2147: (configuration->OverrideHardwarePresent != defaultHardwarePresent)) { ! 2148: ! 2149: SerMouPrint(( ! 2150: 1, ! 2151: "SERMOUSE-SerMouServiceParameters: Pointer port base name = %ws\n", ! 2152: DeviceName->Buffer ! 2153: )); ! 2154: ! 2155: if (configuration->MouseAttributes.InputDataQueueLength == 0) { ! 2156: ! 2157: SerMouPrint(( ! 2158: 1, ! 2159: "SERMOUSE-SerMouServiceParameters: overriding MouseInputDataQueueLength = 0x%x\n", ! 2160: configuration->MouseAttributes.InputDataQueueLength ! 2161: )); ! 2162: ! 2163: configuration->MouseAttributes.InputDataQueueLength = ! 2164: defaultDataQueueSize; ! 2165: } ! 2166: ! 2167: configuration->MouseAttributes.InputDataQueueLength *= ! 2168: sizeof(MOUSE_INPUT_DATA); ! 2169: ! 2170: SerMouPrint(( ! 2171: 1, ! 2172: "SERMOUSE-SerMouServiceParameters: MouseInputDataQueueLength = 0x%x\n", ! 2173: configuration->MouseAttributes.InputDataQueueLength ! 2174: )); ! 2175: ! 2176: configuration->MouseAttributes.NumberOfButtons = numberOfButtons; ! 2177: SerMouPrint(( ! 2178: 1, ! 2179: "SERMOUSE-SerMouServiceParameters: NumberOfButtons = %d\n", ! 2180: configuration->MouseAttributes.NumberOfButtons ! 2181: )); ! 2182: ! 2183: configuration->MouseAttributes.SampleRate = sampleRate; ! 2184: SerMouPrint(( ! 2185: 1, ! 2186: "SERMOUSE-SerMouServiceParameters: SampleRate = %d\n", ! 2187: configuration->MouseAttributes.SampleRate ! 2188: )); ! 2189: } ! 2190: ! 2191: // ! 2192: // Free the allocated memory before returning. ! 2193: // ! 2194: ! 2195: if (parametersPath.Buffer) ! 2196: ExFreePool(parametersPath.Buffer); ! 2197: if (parameters) ! 2198: ExFreePool(parameters); ! 2199: ! 2200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.