Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2445 lines
73 KiB

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