Source code of Windows XP (NT5)
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.

981 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This module contains plug & play code for the serial Mouse Filter Driver,
  7. including code for the creation and removal of serial mouse device contexts.
  8. Environment:
  9. Kernel & user mode.
  10. Revision History:
  11. --*/
  12. #include "mouser.h"
  13. #include "sermlog.h"
  14. #include "debug.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, SerialMouseAddDevice)
  17. #pragma alloc_text(PAGE, SerialMousePnP)
  18. #pragma alloc_text(PAGE, SerialMousePower)
  19. #pragma alloc_text(PAGE, SerialMouseRemoveDevice)
  20. #pragma alloc_text(PAGE, SerialMouseSendIrpSynchronously)
  21. #endif
  22. NTSTATUS
  23. SerialMouseAddDevice (
  24. IN PDRIVER_OBJECT Driver,
  25. IN PDEVICE_OBJECT PDO
  26. )
  27. /*++
  28. Routine Description:
  29. Arguments:
  30. Return Value:
  31. NTSTATUS result code.
  32. --*/
  33. {
  34. NTSTATUS status = STATUS_SUCCESS;
  35. PDEVICE_EXTENSION deviceExtension;
  36. PDEVICE_OBJECT device;
  37. KIRQL oldIrql;
  38. PAGED_CODE();
  39. status = IoCreateDevice(Driver,
  40. sizeof(DEVICE_EXTENSION),
  41. NULL, // no name for this Filter DO
  42. FILE_DEVICE_SERIAL_MOUSE_PORT,
  43. 0,
  44. FALSE,
  45. &device);
  46. if (!NT_SUCCESS(status)) {
  47. return status;
  48. }
  49. deviceExtension = (PDEVICE_EXTENSION) device->DeviceExtension;
  50. Print(deviceExtension, DBG_PNP_TRACE, ("enter Add Device\n"));
  51. //
  52. // Initialize the fields.
  53. //
  54. RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
  55. deviceExtension->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
  56. if (deviceExtension->TopOfStack == NULL) {
  57. PIO_ERROR_LOG_PACKET errorLogEntry;
  58. //
  59. // Not good; in only extreme cases will this fail
  60. //
  61. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  62. IoAllocateErrorLogEntry(Driver,
  63. (UCHAR) sizeof(IO_ERROR_LOG_PACKET));
  64. if (errorLogEntry) {
  65. errorLogEntry->ErrorCode = SERMOUSE_ATTACH_DEVICE_FAILED;
  66. errorLogEntry->DumpDataSize = 0;
  67. errorLogEntry->SequenceNumber = 0;
  68. errorLogEntry->MajorFunctionCode = 0;
  69. errorLogEntry->IoControlCode = 0;
  70. errorLogEntry->RetryCount = 0;
  71. errorLogEntry->UniqueErrorValue = 0;
  72. errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_CONNECTED;
  73. IoWriteErrorLogEntry(errorLogEntry);
  74. }
  75. IoDeleteDevice(device);
  76. return STATUS_DEVICE_NOT_CONNECTED;
  77. }
  78. ASSERT(deviceExtension->TopOfStack);
  79. deviceExtension->PDO = PDO;
  80. deviceExtension->Self = device;
  81. deviceExtension->Removed = FALSE;
  82. deviceExtension->Started = FALSE;
  83. deviceExtension->Stopped = FALSE;
  84. deviceExtension->PowerState = PowerDeviceD0;
  85. deviceExtension->WaitWakePending = FALSE;
  86. KeInitializeSpinLock(&deviceExtension->PnpStateLock);
  87. KeInitializeEvent(&deviceExtension->StopEvent, SynchronizationEvent, FALSE);
  88. IoInitializeRemoveLock(&deviceExtension->RemoveLock, SERMOU_POOL_TAG, 0, 10);
  89. deviceExtension->ReadIrp = IoAllocateIrp( device->StackSize, FALSE );
  90. if (!deviceExtension->ReadIrp) {
  91. //
  92. // The ReadIrp is critical to this driver, if we can't get one, no use
  93. // in going any further
  94. //
  95. IoDetachDevice(deviceExtension->TopOfStack);
  96. IoDeleteDevice(device);
  97. return STATUS_INSUFFICIENT_RESOURCES;
  98. }
  99. deviceExtension->WmiLibInfo.GuidCount = sizeof(WmiGuidList) /
  100. sizeof(WMIGUIDREGINFO);
  101. deviceExtension->WmiLibInfo.GuidList = WmiGuidList;
  102. deviceExtension->WmiLibInfo.QueryWmiRegInfo = SerialMouseQueryWmiRegInfo;
  103. deviceExtension->WmiLibInfo.QueryWmiDataBlock = SerialMouseQueryWmiDataBlock;
  104. deviceExtension->WmiLibInfo.SetWmiDataBlock = SerialMouseSetWmiDataBlock;
  105. deviceExtension->WmiLibInfo.SetWmiDataItem = SerialMouseSetWmiDataItem;
  106. deviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
  107. deviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
  108. IoWMIRegistrationControl(deviceExtension->Self, WMIREG_ACTION_REGISTER);
  109. KeInitializeTimer(&deviceExtension->DelayTimer);
  110. //
  111. // Set all the appropriate device object flags
  112. //
  113. device->Flags &= ~DO_DEVICE_INITIALIZING;
  114. device->Flags |= DO_BUFFERED_IO;
  115. device->Flags |= DO_POWER_PAGABLE;
  116. return status;
  117. }
  118. VOID
  119. SerialMouseRemoveDevice(
  120. PDEVICE_EXTENSION DeviceExtension,
  121. PIRP Irp
  122. )
  123. {
  124. BOOLEAN closePort = FALSE;
  125. PAGED_CODE();
  126. //
  127. // Run the (surprise remove code). If we are surprise removed, then this
  128. // will be called twice. We only run the removal code once.
  129. //
  130. if (!DeviceExtension->SurpriseRemoved) {
  131. DeviceExtension->SurpriseRemoved = TRUE;
  132. //
  133. // Here if we had any outstanding requests in a personal queue we should
  134. // complete them all now.
  135. //
  136. // Note, the device could be GONE so we cannot send it any non-
  137. // PNP IRPS.
  138. //
  139. IoWMIRegistrationControl(DeviceExtension->Self, WMIREG_ACTION_DEREGISTER);
  140. if (DeviceExtension->Started && DeviceExtension->EnableCount > 0) {
  141. Print(DeviceExtension, DBG_PNP_INFO,
  142. ("Cancelling and stopping detection for remove\n"));
  143. IoCancelIrp(DeviceExtension->ReadIrp);
  144. //
  145. // Cancel the detection timer, SerialMouseRemoveLockAndWait will
  146. // guarantee that we don't yank the device from under the polling
  147. // routine
  148. //
  149. SerialMouseStopDetection(DeviceExtension);
  150. }
  151. }
  152. //
  153. // The stack is about to be torn down, make sure that the underlying serial
  154. // port is closed. No other piece of code will be looking at EnableCount if
  155. // Remove is true, so there is no need for InterlockedXxx.
  156. //
  157. if (DeviceExtension->Removed && DeviceExtension->EnableCount > 0) {
  158. Print(DeviceExtension, DBG_PNP_INFO | DBG_PNP_ERROR,
  159. ("sending final close, enable count %d\n",
  160. DeviceExtension->EnableCount));
  161. DeviceExtension->EnableCount = 0;
  162. SerialMouseClosePort(DeviceExtension, Irp);
  163. }
  164. }
  165. NTSTATUS
  166. SerialMouseCompletionRoutine (
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN PIRP Irp,
  169. IN PKEVENT Event
  170. )
  171. /*++
  172. Routine Description:
  173. The pnp IRP is in the process of completing.
  174. signal
  175. Arguments:
  176. Context set to the device object in question.
  177. --*/
  178. {
  179. UNREFERENCED_PARAMETER(DeviceObject);
  180. UNREFERENCED_PARAMETER(Irp);
  181. KeSetEvent(Event, 0, FALSE);
  182. return STATUS_MORE_PROCESSING_REQUIRED;
  183. }
  184. NTSTATUS
  185. SerialMouseSendIrpSynchronously (
  186. IN PDEVICE_OBJECT DeviceObject,
  187. IN PIRP Irp,
  188. IN BOOLEAN CopyToNext
  189. )
  190. {
  191. KEVENT event;
  192. NTSTATUS status;
  193. PAGED_CODE();
  194. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  195. if (CopyToNext) {
  196. IoCopyCurrentIrpStackLocationToNext(Irp);
  197. }
  198. IoSetCompletionRoutine(Irp,
  199. SerialMouseCompletionRoutine,
  200. &event,
  201. TRUE, // on success
  202. TRUE, // on error
  203. TRUE // on cancel
  204. );
  205. status = IoCallDriver(DeviceObject, Irp);
  206. //
  207. // Wait for lower drivers to be done with the Irp
  208. //
  209. if (status == STATUS_PENDING) {
  210. KeWaitForSingleObject(&event,
  211. Executive,
  212. KernelMode,
  213. FALSE,
  214. NULL
  215. );
  216. status = Irp->IoStatus.Status;
  217. }
  218. return status;
  219. }
  220. void
  221. SerialMouseHandleStartStopStart(
  222. IN PDEVICE_EXTENSION DeviceExtension
  223. )
  224. {
  225. KIRQL irql;
  226. KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);
  227. if (DeviceExtension->Stopped) {
  228. DeviceExtension->Stopped = FALSE;
  229. IoReuseIrp(DeviceExtension->ReadIrp, STATUS_SUCCESS);
  230. }
  231. KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);
  232. }
  233. void
  234. SerialMouseStopDevice (
  235. IN PDEVICE_EXTENSION DeviceExtension
  236. )
  237. {
  238. KIRQL irql;
  239. KeAcquireSpinLock(&DeviceExtension->PnpStateLock, &irql);
  240. DeviceExtension->Stopped = TRUE;
  241. KeReleaseSpinLock(&DeviceExtension->PnpStateLock, irql);
  242. if (DeviceExtension->Started) {
  243. Print(DeviceExtension, DBG_PNP_INFO,
  244. ("Cancelling and stopping detection for stop\n"));
  245. DeviceExtension->Started = FALSE;
  246. //
  247. // Stop detection and cancel the read
  248. //
  249. SerialMouseStopDetection(DeviceExtension);
  250. //
  251. // BUGBUG: should I only wait if IoCancelIrp fails?
  252. //
  253. if (!IoCancelIrp(DeviceExtension->ReadIrp)) {
  254. //
  255. // Wait for the read irp to complete
  256. //
  257. Print(DeviceExtension, DBG_PNP_INFO, ("Waiting for stop event\n"));
  258. KeWaitForSingleObject(&DeviceExtension->StopEvent,
  259. Executive,
  260. KernelMode,
  261. FALSE,
  262. NULL
  263. );
  264. Print(DeviceExtension, DBG_PNP_INFO, ("Done waiting for stop event\n"));
  265. }
  266. }
  267. }
  268. NTSTATUS
  269. SerialMousePnP (
  270. IN PDEVICE_OBJECT DeviceObject,
  271. IN PIRP Irp
  272. )
  273. /*++
  274. Routine Description:
  275. The plug and play dispatch routines.
  276. Most of these this filter driver will completely ignore.
  277. In all cases it must pass on the IRP to the lower driver.
  278. Arguments:
  279. DeviceObject - pointer to a device object.
  280. Irp - pointer to an I/O Request Packet.
  281. Return Value:
  282. NT status code
  283. --*/
  284. {
  285. PDEVICE_EXTENSION deviceExtension;
  286. PIO_STACK_LOCATION stack;
  287. HANDLE keyHandle;
  288. NTSTATUS status;
  289. KIRQL oldIrql;
  290. BOOLEAN skipIt = FALSE;
  291. PAGED_CODE();
  292. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  293. stack = IoGetCurrentIrpStackLocation(Irp);
  294. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
  295. if (!NT_SUCCESS(status)) {
  296. //
  297. // Someone gave us a pnp irp after a remove. Unthinkable!
  298. //
  299. ASSERT(FALSE);
  300. Irp->IoStatus.Information = 0;
  301. Irp->IoStatus.Status = status;
  302. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  303. return status;
  304. }
  305. Print(deviceExtension, DBG_PNP_TRACE,
  306. ("PnP Enter (min func=0x%x)\n", stack->MinorFunction));
  307. switch (stack->MinorFunction) {
  308. case IRP_MN_START_DEVICE:
  309. //
  310. // Send the actual start down the stack
  311. //
  312. status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
  313. Irp,
  314. TRUE);
  315. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  316. PIO_STACK_LOCATION nextStack;
  317. //
  318. // If a create has not been sent down the stack yet, then send one
  319. // now. The serial port driver reequires a create before
  320. // any reads or IOCTLS are to be sent.
  321. //
  322. if (InterlockedIncrement(&deviceExtension->EnableCount) == 1) {
  323. NTSTATUS prevStatus;
  324. ULONG_PTR prevInformation;
  325. //
  326. // No previous create has been sent, send one now
  327. //
  328. prevStatus = Irp->IoStatus.Status;
  329. prevInformation = Irp->IoStatus.Information;
  330. nextStack = IoGetNextIrpStackLocation (Irp);
  331. RtlZeroMemory(nextStack, sizeof(IO_STACK_LOCATION));
  332. nextStack->MajorFunction = IRP_MJ_CREATE;
  333. status =
  334. SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
  335. Irp,
  336. FALSE);
  337. Print(deviceExtension, DBG_PNP_NOISE,
  338. ("Create for start 0x%x\n", status));
  339. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  340. Irp->IoStatus.Status = prevStatus;
  341. Irp->IoStatus.Information = prevInformation;
  342. }
  343. else {
  344. Print(deviceExtension, DBG_CC_ERROR | DBG_PNP_ERROR,
  345. ("Create for start failed, 0x%x!\n", status));
  346. goto SerialMouseStartFinished;
  347. }
  348. }
  349. //
  350. // Open the device registry key and read the devnode stored values
  351. //
  352. status = IoOpenDeviceRegistryKey(deviceExtension->PDO,
  353. PLUGPLAY_REGKEY_DEVICE,
  354. STANDARD_RIGHTS_READ,
  355. &keyHandle);
  356. if (NT_SUCCESS(status)) {
  357. SerialMouseServiceParameters(deviceExtension, keyHandle);
  358. ZwClose(keyHandle);
  359. }
  360. //
  361. // Handle the transition from start to stop to start correctly
  362. //
  363. SerialMouseHandleStartStopStart(deviceExtension);
  364. //
  365. // Initialize the device to make sure we can start it and report
  366. // data from it
  367. //
  368. status = SerialMouseInitializeDevice(deviceExtension);
  369. Print(deviceExtension, DBG_PNP_INFO,
  370. ("Start InitializeDevice 0x%x\n", status));
  371. if (InterlockedDecrement(&deviceExtension->EnableCount) == 0) {
  372. //
  373. // We will start the read loop when we receive a "real" create
  374. // from the raw input thread. We do not keep our own create
  375. // around after the start device because it will mess up the
  376. // logic for handling QUERY_REMOVE (our "fake" create will still
  377. // be in effect and the QUERY_REMOVE will fail).
  378. //
  379. Print(deviceExtension, DBG_PNP_NOISE,
  380. ("sending close for start\n"));
  381. SerialMouseClosePort(deviceExtension, Irp);
  382. }
  383. else {
  384. //
  385. // We already have an outstanding create, just spin up the read
  386. // loop again
  387. //
  388. ASSERT(deviceExtension->EnableCount >= 1);
  389. Print(deviceExtension, DBG_PNP_INFO,
  390. ("spinning up read in start\n"));
  391. status = SerialMouseSpinUpRead(deviceExtension);
  392. }
  393. }
  394. SerialMouseStartFinished:
  395. Irp->IoStatus.Status = status;
  396. Irp->IoStatus.Information = 0;
  397. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  398. break;
  399. case IRP_MN_STOP_DEVICE:
  400. //
  401. // After the start IRP has been sent to the lower driver object, the
  402. // bus may NOT send any more IRPS down ``touch'' until another START
  403. // has occured.
  404. // What ever access is required must be done before the Irp is passed
  405. // on.
  406. //
  407. SerialMouseStopDevice(deviceExtension);
  408. //
  409. // We don't need a completion routine so fire and forget.
  410. //
  411. skipIt = TRUE;
  412. Irp->IoStatus.Status = STATUS_SUCCESS;
  413. break;
  414. case IRP_MN_SURPRISE_REMOVAL:
  415. SerialMouseRemoveDevice(deviceExtension, Irp);
  416. skipIt = TRUE;
  417. Irp->IoStatus.Status = STATUS_SUCCESS;
  418. break;
  419. case IRP_MN_REMOVE_DEVICE:
  420. //
  421. // The PlugPlay system has dictacted the removal of this device. We
  422. // have no choise but to detach and delete the device objecct.
  423. // (If we wanted to express and interest in preventing this removal,
  424. // we should have filtered the query remove and query stop routines.)
  425. //
  426. // Note! we might receive a remove WITHOUT first receiving a stop.
  427. //
  428. Print(deviceExtension, DBG_PNP_TRACE, ("enter RemoveDevice \n"));
  429. deviceExtension->Removed = TRUE;
  430. SerialMouseRemoveDevice(deviceExtension, Irp);
  431. //
  432. // Send on the remove IRP
  433. //
  434. Irp->IoStatus.Status = STATUS_SUCCESS;
  435. IoSkipCurrentIrpStackLocation(Irp);
  436. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  437. //
  438. // Wait for the remove lock to free.
  439. //
  440. IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
  441. //
  442. // Free the associated memory.
  443. //
  444. IoFreeIrp(deviceExtension->ReadIrp);
  445. deviceExtension->ReadIrp = NULL;
  446. if (deviceExtension->DetectionIrp) {
  447. IoFreeIrp(deviceExtension->DetectionIrp);
  448. deviceExtension->DetectionIrp = NULL;
  449. }
  450. Print(deviceExtension, DBG_PNP_NOISE, ("remove and wait done\n"));
  451. IoDetachDevice(deviceExtension->TopOfStack);
  452. IoDeleteDevice(deviceExtension->Self);
  453. return status;
  454. case IRP_MN_QUERY_CAPABILITIES:
  455. status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
  456. Irp,
  457. TRUE);
  458. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  459. PDEVICE_CAPABILITIES devCaps;
  460. devCaps = stack->Parameters.DeviceCapabilities.Capabilities;
  461. if (devCaps) {
  462. SYSTEM_POWER_STATE i;
  463. //
  464. // We do not want to show up in the hot plug removal applet
  465. //
  466. devCaps->SurpriseRemovalOK = TRUE;
  467. //
  468. // While the underlying serial bus might be able to wake the
  469. // machine from low power (via wake on ring), the mouse cannot.
  470. //
  471. devCaps->SystemWake = PowerSystemUnspecified;
  472. devCaps->DeviceWake = PowerDeviceUnspecified;
  473. devCaps->WakeFromD0 =
  474. devCaps->WakeFromD1 =
  475. devCaps->WakeFromD2 =
  476. devCaps->WakeFromD3 = FALSE;
  477. devCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  478. for (i = PowerSystemSleeping1; i < PowerSystemMaximum; i++) {
  479. devCaps->DeviceState[i] = PowerDeviceD3;
  480. }
  481. }
  482. }
  483. //
  484. // status, Irp->IoStatus.Status set above
  485. //
  486. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  487. break;
  488. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  489. status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
  490. Irp,
  491. TRUE);
  492. //
  493. // If the lower filter does not support this Irp, this is
  494. // OK, we can ignore this error
  495. //
  496. if (status == STATUS_NOT_SUPPORTED ||
  497. status == STATUS_INVALID_DEVICE_REQUEST) {
  498. status = STATUS_SUCCESS;
  499. }
  500. if (NT_SUCCESS(status) && deviceExtension->RemovalDetected) {
  501. (PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_REMOVED;
  502. }
  503. if (!NT_SUCCESS(status)) {
  504. Print(deviceExtension, DBG_PNP_ERROR,
  505. ("error pending query pnp device state event (0x%x)\n",
  506. status
  507. ));
  508. }
  509. //
  510. // Irp->IoStatus.Information will contain the new i/o resource
  511. // requirements list so leave it alone
  512. //
  513. Irp->IoStatus.Status = status;
  514. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  515. break;
  516. case IRP_MN_QUERY_REMOVE_DEVICE:
  517. case IRP_MN_CANCEL_REMOVE_DEVICE:
  518. case IRP_MN_QUERY_STOP_DEVICE:
  519. case IRP_MN_CANCEL_STOP_DEVICE:
  520. case IRP_MN_QUERY_DEVICE_RELATIONS:
  521. case IRP_MN_QUERY_INTERFACE:
  522. case IRP_MN_QUERY_RESOURCES:
  523. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  524. case IRP_MN_READ_CONFIG:
  525. case IRP_MN_WRITE_CONFIG:
  526. case IRP_MN_EJECT:
  527. case IRP_MN_SET_LOCK:
  528. case IRP_MN_QUERY_ID:
  529. default:
  530. skipIt = TRUE;
  531. break;
  532. }
  533. if (skipIt) {
  534. //
  535. // Don't touch the irp...
  536. //
  537. IoSkipCurrentIrpStackLocation(Irp);
  538. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  539. }
  540. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  541. Print(deviceExtension, DBG_PNP_TRACE, ("PnP exit (%x)\n", status));
  542. return status;
  543. }
  544. typedef struct _MOUSER_START_WORKITEM {
  545. PDEVICE_EXTENSION DeviceExtension;
  546. PIO_WORKITEM WorkItem;
  547. } MOUSER_START_WORKITEM, *PMOUSER_START_WORKITEM;
  548. VOID
  549. StartDeviceWorker (
  550. IN PDEVICE_OBJECT DeviceObject,
  551. IN PMOUSER_START_WORKITEM WorkItemContext
  552. )
  553. {
  554. PDEVICE_EXTENSION deviceExtension = WorkItemContext->DeviceExtension;
  555. NTSTATUS status;
  556. PIRP irp;
  557. if (deviceExtension->Started &&
  558. !deviceExtension->Removed &&
  559. deviceExtension->EnableCount > 0) {
  560. irp = IoAllocateIrp( deviceExtension->Self->StackSize, FALSE );
  561. if (irp) {
  562. status = SerialMouseStartDevice(deviceExtension,
  563. irp,
  564. FALSE);
  565. if (!NT_SUCCESS(status)) {
  566. KEVENT event;
  567. IO_STATUS_BLOCK iosb;
  568. Print(deviceExtension, DBG_POWER_INFO,
  569. ("mouse not found on power up, 0x%x\n", status));
  570. //
  571. // The device has been removed or is not detectable
  572. // after powering back up ... have serenum do the
  573. // removal work
  574. //
  575. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  576. SerialMouseIoSyncInternalIoctl(
  577. IOCTL_INTERNAL_SERENUM_REMOVE_SELF,
  578. deviceExtension->TopOfStack,
  579. &event,
  580. &iosb
  581. );
  582. }
  583. IoFreeIrp(irp);
  584. }
  585. }
  586. IoFreeWorkItem(WorkItemContext->WorkItem);
  587. ExFreePool(WorkItemContext);
  588. IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
  589. }
  590. NTSTATUS
  591. SerialMousePower (
  592. IN PDEVICE_OBJECT DeviceObject,
  593. IN PIRP Irp
  594. )
  595. /*++
  596. Routine Description:
  597. The power dispatch routine.
  598. All we care about is the transition from a low D state to D0.
  599. Arguments:
  600. DeviceObject - pointer to a device object.
  601. Irp - pointer to an I/O Request Packet.
  602. Return Value:
  603. NT status code
  604. --*/
  605. {
  606. PIO_STACK_LOCATION stack;
  607. NTSTATUS status = STATUS_SUCCESS;
  608. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  609. POWER_STATE powerState;
  610. POWER_STATE_TYPE powerType;
  611. KEVENT event;
  612. IO_STATUS_BLOCK iosb;
  613. LARGE_INTEGER li;
  614. PAGED_CODE();
  615. Print(deviceExtension, DBG_POWER_TRACE, ("Power Enter.\n"));
  616. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  617. stack = IoGetCurrentIrpStackLocation(Irp);
  618. powerType = stack->Parameters.Power.Type;
  619. powerState = stack->Parameters.Power.State;
  620. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
  621. if (!NT_SUCCESS(status)) {
  622. PoStartNextPowerIrp(Irp);
  623. Irp->IoStatus.Status = status;
  624. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  625. return status;
  626. }
  627. switch (stack->MinorFunction) {
  628. case IRP_MN_WAIT_WAKE:
  629. break;
  630. case IRP_MN_SET_POWER:
  631. //
  632. // Let system power irps fall through
  633. //
  634. if (powerType == DevicePowerState &&
  635. powerState.DeviceState != deviceExtension->PowerState) {
  636. switch (powerState.DeviceState) {
  637. case PowerDeviceD0:
  638. //
  639. // Transitioning from a low D state to D0
  640. //
  641. Print(deviceExtension, DBG_POWER_INFO,
  642. ("Powering up to PowerDeviceD0\n"));
  643. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  644. deviceExtension->PoweringDown = FALSE;
  645. deviceExtension->PowerState =
  646. stack->Parameters.Power.State.DeviceState;
  647. IoCopyCurrentIrpStackLocationToNext(Irp);
  648. IoSetCompletionRoutine(Irp,
  649. SerialMouseCompletionRoutine,
  650. &event,
  651. TRUE, // on success
  652. TRUE, // on error
  653. TRUE // on cancel
  654. );
  655. status = PoCallDriver(deviceExtension->TopOfStack, Irp);
  656. //
  657. // Wait for lower drivers to be done with the Irp
  658. //
  659. if (status == STATUS_PENDING) {
  660. KeWaitForSingleObject(&event,
  661. Executive,
  662. KernelMode,
  663. FALSE,
  664. NULL
  665. );
  666. status = Irp->IoStatus.Status;
  667. }
  668. if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
  669. PoSetPowerState(DeviceObject, powerType, powerState);
  670. if (NT_SUCCESS(IoAcquireRemoveLock(&deviceExtension->RemoveLock, deviceExtension))) {
  671. PIO_WORKITEM workItem;
  672. PMOUSER_START_WORKITEM workItemContext;
  673. workItem = IoAllocateWorkItem(DeviceObject);
  674. if (workItem) {
  675. workItemContext = ExAllocatePool(NonPagedPool, sizeof(MOUSER_START_WORKITEM));
  676. if (workItemContext) {
  677. workItemContext->WorkItem = workItem;
  678. workItemContext->DeviceExtension = deviceExtension;
  679. IoQueueWorkItem(
  680. workItem,
  681. StartDeviceWorker,
  682. DelayedWorkQueue,
  683. workItemContext);
  684. } else {
  685. IoFreeWorkItem(workItem);
  686. IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
  687. }
  688. } else {
  689. IoReleaseRemoveLock(&deviceExtension->RemoveLock, deviceExtension);
  690. }
  691. }
  692. }
  693. Irp->IoStatus.Status = status;
  694. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  695. PoStartNextPowerIrp(Irp);
  696. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  697. return status;
  698. case PowerDeviceD1:
  699. case PowerDeviceD2:
  700. case PowerDeviceD3:
  701. deviceExtension->PoweringDown = TRUE;
  702. // If a wait wake is pending against the mouse, keep it powered
  703. //
  704. if (deviceExtension->WaitWakePending) {
  705. Print(deviceExtension, DBG_POWER_INFO,
  706. ("Ignoring power down for wait wake (-> D%d)\n",
  707. powerState.DeviceState-1
  708. ));
  709. break;
  710. }
  711. Print(deviceExtension, DBG_POWER_INFO,
  712. ("Powering down to PowerDeviceD%d\n",
  713. powerState.DeviceState-1
  714. ));
  715. //
  716. // Acquire another reference to the lock so that the decrement
  717. // in the cancel section of the completion routine will not fall
  718. // to zero (and have the remlock think we are removed)
  719. //
  720. // status = IoAcquireRemoveLock(&deviceExtension->RemoveLock,
  721. // deviceExtension->ReadIrp);
  722. ASSERT(NT_SUCCESS(status));
  723. deviceExtension->PowerState =
  724. stack->Parameters.Power.State.DeviceState;
  725. //
  726. // Cancel the read irp so that it won't conflict with power up
  727. // initialization (which involves some reads against the port)
  728. //
  729. IoCancelIrp(deviceExtension->ReadIrp);
  730. //
  731. // We don't want the powering down of the port to be confused
  732. // with removal
  733. //
  734. SerialMouseStopDetection(deviceExtension);
  735. //
  736. // Power down the device by clearing RTS and waiting 150 ms
  737. //
  738. Print(deviceExtension, DBG_POWER_INFO, ("Clearing RTS...\n"));
  739. KeInitializeEvent(&event, NotificationEvent, FALSE);
  740. status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_RTS,
  741. deviceExtension->TopOfStack,
  742. &event,
  743. &iosb
  744. );
  745. if (NT_SUCCESS(status)) {
  746. Print(deviceExtension, DBG_POWER_INFO, ("150ms wait\n"));
  747. li.QuadPart = (LONGLONG) -PAUSE_150_MS;
  748. KeDelayExecutionThread(KernelMode, FALSE, &li);
  749. }
  750. PoSetPowerState(DeviceObject,
  751. stack->Parameters.Power.Type,
  752. stack->Parameters.Power.State);
  753. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  754. //
  755. // Fire and forget
  756. //
  757. Irp->IoStatus.Status = STATUS_SUCCESS;
  758. IoCopyCurrentIrpStackLocationToNext(Irp);
  759. PoStartNextPowerIrp(Irp);
  760. return PoCallDriver(deviceExtension->TopOfStack, Irp);
  761. }
  762. }
  763. break;
  764. case IRP_MN_QUERY_POWER:
  765. break;
  766. default:
  767. Print(deviceExtension, DBG_POWER_ERROR,
  768. ("Power minor (0x%x) is not handled\n", stack->MinorFunction));
  769. }
  770. //
  771. // Must call the Po versions of these functions or bad things (tm) will happen!
  772. //
  773. PoStartNextPowerIrp(Irp);
  774. IoSkipCurrentIrpStackLocation(Irp);
  775. status = PoCallDriver(deviceExtension->TopOfStack, Irp);
  776. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  777. return status;
  778. }