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.

337 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. ptdrvmou.c
  5. Abstract:
  6. Mouse specific parts of the RDP remote port driver.
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. 02/12/99 - Initial Revision based on pnpi8042 driver
  11. --*/
  12. #include <precomp.h>
  13. #pragma hdrstop
  14. #include "ptdrvcom.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, PtMouseConfiguration)
  17. #pragma alloc_text(PAGE, PtMouseStartDevice)
  18. #endif
  19. NTSTATUS
  20. PtMouseConfiguration(
  21. IN PPORT_MOUSE_EXTENSION MouseExtension,
  22. IN PCM_RESOURCE_LIST ResourceList
  23. )
  24. /*++
  25. Routine Description:
  26. This routine retrieves the configuration information for the mouse.
  27. Arguments:
  28. MouseExtension - Mouse extension
  29. ResourceList - Translated resource list give to us via the start IRP
  30. Return Value:
  31. STATUS_SUCCESS if all the resources required are presented
  32. --*/
  33. {
  34. NTSTATUS status = STATUS_SUCCESS;
  35. PCM_PARTIAL_RESOURCE_LIST partialResList = NULL;
  36. PCM_PARTIAL_RESOURCE_DESCRIPTOR firstResDesc = NULL,
  37. currentResDesc = NULL;
  38. PCM_FULL_RESOURCE_DESCRIPTOR fullResDesc = NULL;
  39. PI8042_CONFIGURATION_INFORMATION configuration;
  40. ULONG count,
  41. i;
  42. PAGED_CODE();
  43. if (ResourceList) {
  44. fullResDesc = ResourceList->List;
  45. if (!fullResDesc) {
  46. //
  47. // this should never happen
  48. //
  49. ASSERT(fullResDesc != NULL);
  50. return STATUS_INSUFFICIENT_RESOURCES;
  51. }
  52. SET_HW_FLAGS(MOUSE_HARDWARE_PRESENT);
  53. configuration = &Globals.ControllerData->Configuration;
  54. partialResList = &fullResDesc->PartialResourceList;
  55. currentResDesc = firstResDesc = partialResList->PartialDescriptors;
  56. count = partialResList->Count;
  57. //
  58. // NOTE: not all of the resources associated with the i8042 may be given at
  59. // this time. From empirical tests, the mouse is only associated with its
  60. // interrupt, while the keyboard will receive the ports along with its
  61. // interrupt
  62. //
  63. for (i = 0; i < count; i++, currentResDesc++) {
  64. switch (currentResDesc->Type) {
  65. case CmResourceTypePort:
  66. //
  67. // Copy the port information. We will sort the port list
  68. // into ascending order based on the starting port address
  69. // later (note that we *know* there are a max of two port
  70. // ranges for the i8042).
  71. //
  72. Print(DBG_SS_NOISE, ("io flags are 0x%x\n", currentResDesc->Flags));
  73. if (configuration->PortListCount < MaximumPortCount) {
  74. configuration->PortList[configuration->PortListCount] = *currentResDesc;
  75. configuration->PortListCount += 1;
  76. }
  77. else {
  78. Print(DBG_SS_INFO | DBG_SS_ERROR,
  79. ("Mouse::PortListCount already at max (%d)",
  80. configuration->PortListCount
  81. ));
  82. }
  83. break;
  84. default:
  85. Print(DBG_ALWAYS,
  86. ("resource type 0x%x unhandled...\n",
  87. (LONG) currentResDesc->Type
  88. ));
  89. break;
  90. }
  91. }
  92. }
  93. else {
  94. Print(DBG_SS_INFO | DBG_SS_TRACE, ("mouse with null resources\n"));
  95. }
  96. if (NT_SUCCESS(status)) {
  97. Globals.ControllerData->HardwarePresent |= MOUSE_HARDWARE_INITIALIZED;
  98. }
  99. return status;
  100. }
  101. VOID
  102. PtSendCurrentMouseInput(
  103. IN PDEVICE_OBJECT DeviceObject,
  104. IN PMOUSE_INPUT_DATA pInput,
  105. IN ULONG ulEntries
  106. )
  107. /*++
  108. Routine Description:
  109. This routine calls the mouse class driver until all the data has been
  110. queued.
  111. Arguments:
  112. DeviceObject - Pointer to the device object
  113. Return Value:
  114. None
  115. --*/
  116. {
  117. PPORT_MOUSE_EXTENSION deviceExtension;
  118. LARGE_INTEGER SleepTime;
  119. NTSTATUS Status;
  120. PUCHAR pEnd;
  121. Print(DBG_DPC_NOISE, ("PtSendCurrentMouseInput: enter\n"));
  122. if (DeviceObject != NULL) {
  123. deviceExtension = DeviceObject->DeviceExtension;
  124. if (deviceExtension->EnableCount) {
  125. PVOID classService;
  126. PVOID classDeviceObject;
  127. ULONG dataNotConsumed = 0;
  128. ULONG inputDataConsumed = 0;
  129. //
  130. // Call the connected class driver's callback ISR with the supplied data
  131. //
  132. classDeviceObject = deviceExtension->ConnectData.ClassDeviceObject;
  133. classService = deviceExtension->ConnectData.ClassService;
  134. ASSERT(classService != NULL);
  135. Print(DBG_DPC_NOISE,
  136. ("PtSendCurrentMouseInput: calling class callback (%p, %ld)\n",
  137. pInput, ulEntries));
  138. dataNotConsumed = ulEntries;
  139. pEnd = (PUCHAR)pInput + (ulEntries * sizeof(MOUSE_INPUT_DATA));
  140. while (dataNotConsumed)
  141. {
  142. KIRQL oldIrql;
  143. inputDataConsumed = 0;
  144. //
  145. // Class Service Callback routines need to be execusted at
  146. // DISPATCH_LEVEL, so raise IRQL before calling the callback.
  147. //
  148. KeRaiseIrql( DISPATCH_LEVEL, &oldIrql);
  149. (*(PSERVICE_CALLBACK_ROUTINE) classService)(
  150. classDeviceObject,
  151. pInput,
  152. pEnd,
  153. &inputDataConsumed);
  154. //
  155. // reset the IRQL.
  156. //
  157. KeLowerIrql( oldIrql );
  158. dataNotConsumed = ((ULONG)(pEnd - (PUCHAR)pInput)
  159. /sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
  160. Print(DBG_DPC_INFO,
  161. ("PtSendCurrentMouseInput: Call callback consumed %d items, left %d\n",
  162. inputDataConsumed,
  163. dataNotConsumed));
  164. if (dataNotConsumed)
  165. {
  166. //
  167. // update the input pointer
  168. //
  169. pInput = (PMOUSE_INPUT_DATA)((PUCHAR)pInput +
  170. inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
  171. //
  172. // sleep for 1 ms
  173. //
  174. SleepTime = RtlEnlargedIntegerMultiply( 1, -10000 );
  175. Status = KeDelayExecutionThread( KernelMode, TRUE, &SleepTime );
  176. }
  177. }
  178. }
  179. } else {
  180. Print(DBG_DPC_ERROR, ("PtSendCurrentMouseInput called with NULL Mouse Device Object\n"));
  181. }
  182. Print(DBG_DPC_NOISE, ("PtSendCurrentMouseInput: exit\n"));
  183. }
  184. NTSTATUS
  185. PtMouseStartDevice(
  186. PPORT_MOUSE_EXTENSION MouseExtension,
  187. IN PCM_RESOURCE_LIST ResourceList
  188. )
  189. /*++
  190. Routine Description:
  191. Configures the mouse's device extension (ie allocation of pool,
  192. initialization of DPCs, etc). If the mouse is the last device to start,
  193. it will also initialize the hardware and connect all the interrupts.
  194. Arguments:
  195. MouseExtension - Mouse extesnion
  196. ResourceList - Translated resource list for this device
  197. Return Value:
  198. STATUS_SUCCESSFUL if successful,
  199. --*/
  200. {
  201. NTSTATUS status = STATUS_SUCCESS;
  202. PAGED_CODE();
  203. Print(DBG_SS_TRACE, ("PtMouseStartDevice, enter\n"));
  204. //
  205. // Check to see if a mouse has been started. If so, fail this start.
  206. //
  207. if (MOUSE_INITIALIZED()) {
  208. Print(DBG_SS_ERROR, ("too many mice!\n"));
  209. //
  210. // This is not really necessary because the value won't ever be checked
  211. // in the context of seeing if all the mice were bogus, but it is
  212. // done so that Globals.AddedMice == # of actual started mice
  213. //
  214. InterlockedDecrement(&Globals.AddedMice);
  215. status = STATUS_NO_SUCH_DEVICE;
  216. goto PtMouseStartDeviceExit;
  217. }
  218. else if (MouseExtension->ConnectData.ClassService == NULL) {
  219. //
  220. // No class driver on top of us == BAD BAD BAD
  221. //
  222. // Fail the start of this device in the hope that there is another stack
  223. // that is correctly formed. Another side affect of having no class
  224. // driver is that the AddedMice count is not incremented for this
  225. // device
  226. //
  227. Print(DBG_SS_ERROR, ("Mouse started with out a service cb!\n"));
  228. status = STATUS_INVALID_DEVICE_STATE;
  229. goto PtMouseStartDeviceExit;
  230. }
  231. //
  232. // Parse and store all of the resources associated with the mouse
  233. //
  234. status = PtMouseConfiguration(MouseExtension,
  235. ResourceList
  236. );
  237. if (!NT_SUCCESS(status)) {
  238. PtManuallyRemoveDevice(GET_COMMON_DATA(MouseExtension));
  239. goto PtMouseStartDeviceExit;
  240. }
  241. ASSERT( MOUSE_PRESENT() );
  242. Globals.MouseExtension = MouseExtension;
  243. PtInitWmi(GET_COMMON_DATA(MouseExtension));
  244. MouseExtension->Initialized = TRUE;
  245. PtMouseStartDeviceExit:
  246. Print(DBG_SS_INFO,
  247. ("PtMouseStartDevice %s\n",
  248. NT_SUCCESS(status) ? "successful" : "unsuccessful"
  249. ));
  250. Print(DBG_SS_TRACE, ("PtMouseStartDevice exit (0x%x)\n", status));
  251. return status;
  252. }