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.

1017 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. hid.c
  5. Abstract:
  6. This module contains the code for translating HID reports to keyboard
  7. reports.
  8. Environment:
  9. Kernel & user mode
  10. Revision History:
  11. Nov-96 : Created by Kenneth D. Ray
  12. --*/
  13. //
  14. // For this module only we set the INITGUID macro before including wdm and
  15. // hidclass.h This not only declares the guids but also initializes them.
  16. //
  17. #include "kbdhid.h"
  18. #include "hidclass.h"
  19. #include <initguid.h>
  20. #include <wdmguid.h>
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE,KbdHid_CallHidClass)
  23. #pragma alloc_text(PAGE,KbdHid_AddDevice)
  24. #pragma alloc_text(PAGE,KbdHid_StartDevice)
  25. #pragma alloc_text(PAGE,KbdHid_PnP)
  26. #endif
  27. NTSTATUS
  28. KbdHid_CallHidClass(
  29. IN PDEVICE_EXTENSION Data,
  30. IN ULONG Ioctl,
  31. PVOID InputBuffer,
  32. ULONG InputBufferLength,
  33. PVOID OutputBuffer,
  34. ULONG OutputBufferLength
  35. )
  36. /*++
  37. Routine Description:
  38. Make a *synchronous* request of the HID class driver
  39. Arguments:
  40. Ioctl - Value of the IOCTL request.
  41. InputBuffer - Buffer to be sent to the HID class driver.
  42. InputBufferLength - Size of buffer to be sent to the HID class driver.
  43. OutputBuffer - Buffer for received data from the HID class driver.
  44. OutputBufferLength - Size of receive buffer from the HID class.
  45. Return Value:
  46. STATUS_SUCCESS if successful,
  47. STATUS_UNSUCCESSFUL otherwise
  48. --*/
  49. {
  50. KEVENT event;
  51. PIRP irp;
  52. IO_STATUS_BLOCK ioStatus;
  53. PIO_STACK_LOCATION nextStack;
  54. NTSTATUS status = STATUS_SUCCESS;
  55. PAGED_CODE ();
  56. Print(DBG_PNP_TRACE, ("PNP-CallHidClass: Enter." ));
  57. //
  58. // issue a synchronous request
  59. //
  60. KeInitializeEvent(&event, NotificationEvent, FALSE);
  61. irp = IoBuildDeviceIoControlRequest (
  62. Ioctl,
  63. Data->TopOfStack,
  64. InputBuffer,
  65. InputBufferLength,
  66. OutputBuffer,
  67. OutputBufferLength,
  68. FALSE, // External
  69. &event,
  70. &ioStatus);
  71. if (NULL == irp) {
  72. return STATUS_UNSUCCESSFUL;
  73. }
  74. //
  75. // Call the class driver to perform the operation. If the returned status
  76. // is PENDING, wait for the request to complete.
  77. //
  78. nextStack = IoGetNextIrpStackLocation(irp);
  79. ASSERT(nextStack != NULL);
  80. status = IoCallDriver(Data->TopOfStack, irp);
  81. if (status == STATUS_PENDING) {
  82. status = KeWaitForSingleObject(
  83. &event,
  84. Executive, // wait reason
  85. KernelMode,
  86. FALSE, // we are not alertable
  87. NULL); // No time out !!!!
  88. }
  89. if (NT_SUCCESS (status)) {
  90. status = ioStatus.Status;
  91. }
  92. Print(DBG_PNP_TRACE, ("PNP-CallHidClass: Enter." ));
  93. return status;
  94. }
  95. NTSTATUS
  96. KbdHid_QueryDeviceKey (
  97. IN HANDLE Handle,
  98. IN PWCHAR ValueNameString,
  99. OUT PVOID Data,
  100. IN ULONG DataLength
  101. )
  102. {
  103. NTSTATUS status;
  104. UNICODE_STRING valueName;
  105. ULONG length;
  106. PKEY_VALUE_FULL_INFORMATION fullInfo;
  107. RtlInitUnicodeString (&valueName, ValueNameString);
  108. length = sizeof (KEY_VALUE_FULL_INFORMATION)
  109. + valueName.MaximumLength
  110. + DataLength;
  111. fullInfo = ExAllocatePool (PagedPool, length);
  112. if (fullInfo) {
  113. status = ZwQueryValueKey (Handle,
  114. &valueName,
  115. KeyValueFullInformation,
  116. fullInfo,
  117. length,
  118. &length);
  119. if (NT_SUCCESS (status)) {
  120. ASSERT (DataLength == fullInfo->DataLength);
  121. RtlCopyMemory (Data,
  122. ((PUCHAR) fullInfo) + fullInfo->DataOffset,
  123. fullInfo->DataLength);
  124. }
  125. ExFreePool (fullInfo);
  126. } else {
  127. status = STATUS_NO_MEMORY;
  128. }
  129. return status;
  130. }
  131. NTSTATUS
  132. KbdHid_AddDevice (
  133. IN PDRIVER_OBJECT Driver,
  134. IN PDEVICE_OBJECT PDO
  135. )
  136. /*++
  137. Routine Description:
  138. Arguments:
  139. Return Value:
  140. NTSTATUS result code.
  141. --*/
  142. {
  143. NTSTATUS status = STATUS_SUCCESS;
  144. PDEVICE_EXTENSION data;
  145. PDEVICE_OBJECT device;
  146. POWER_STATE state;
  147. PAGED_CODE ();
  148. Print (DBG_PNP_TRACE, ("enter Add Device \n"));
  149. status = IoCreateDevice(Driver,
  150. sizeof(DEVICE_EXTENSION),
  151. NULL, // no name for this Filter DO
  152. FILE_DEVICE_KEYBOARD,
  153. 0,
  154. FALSE,
  155. &device);
  156. if (!NT_SUCCESS (status)) {
  157. return(status);
  158. }
  159. data = (PDEVICE_EXTENSION) device->DeviceExtension;
  160. //
  161. // Initialize the fields.
  162. //
  163. data->TopOfStack = IoAttachDeviceToDeviceStack (device, PDO);
  164. if (data->TopOfStack == NULL) {
  165. PIO_ERROR_LOG_PACKET errorLogEntry;
  166. //
  167. // Not good; in only extreme cases will this fail
  168. //
  169. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  170. IoAllocateErrorLogEntry(Driver,
  171. (UCHAR) sizeof(IO_ERROR_LOG_PACKET));
  172. if (errorLogEntry) {
  173. errorLogEntry->ErrorCode = KBDHID_ATTACH_DEVICE_FAILED;
  174. errorLogEntry->DumpDataSize = 0;
  175. errorLogEntry->SequenceNumber = 0;
  176. errorLogEntry->MajorFunctionCode = 0;
  177. errorLogEntry->IoControlCode = 0;
  178. errorLogEntry->RetryCount = 0;
  179. errorLogEntry->UniqueErrorValue = 0;
  180. errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_CONNECTED;
  181. IoWriteErrorLogEntry(errorLogEntry);
  182. }
  183. IoDeleteDevice(device);
  184. return STATUS_DEVICE_NOT_CONNECTED;
  185. }
  186. ASSERT (data->TopOfStack);
  187. data->Self = device;
  188. data->Started = FALSE;
  189. data->Initialized = FALSE;
  190. data->UnitId = (USHORT) InterlockedIncrement (&Globals.UnitId);
  191. data->PDO = PDO;
  192. KeInitializeSpinLock(&data->usageMappingSpinLock);
  193. data->ReadIrp = IoAllocateIrp (data->TopOfStack->StackSize, FALSE);
  194. // Initializiation happens automatically.
  195. if (NULL == data->ReadIrp) {
  196. IoDetachDevice (data->TopOfStack);
  197. IoDeleteDevice (device);
  198. return STATUS_INSUFFICIENT_RESOURCES;
  199. }
  200. KeInitializeEvent (&data->ReadCompleteEvent, SynchronizationEvent, FALSE);
  201. KeInitializeEvent (&data->ReadSentEvent, NotificationEvent, TRUE);
  202. IoInitializeRemoveLock (&data->RemoveLock, KBDHID_POOL_TAG, 1, 10);
  203. data->ReadFile = NULL;
  204. ExInitializeFastMutex (&data->CreateCloseMutex);
  205. data->InputData.UnitId = data->UnitId;
  206. data->InputData.MakeCode = 0;
  207. data->InputData.Flags = 0;
  208. data->ScanState = Normal;
  209. //
  210. // Initialize the keyboard attributes structure. This information is
  211. // queried via IOCTL_KEYBOARD_QUERY_ATTRIBUTES. [DAN]
  212. //
  213. data->Attributes.KeyboardIdentifier.Type = HID_KEYBOARD_IDENTIFIER_TYPE;
  214. data->Attributes.KeyboardIdentifier.Subtype = 0;
  215. data->IdEx.Type = HID_KEYBOARD_IDENTIFIER_TYPE;
  216. data->IdEx.Subtype = 0;
  217. data->Attributes.KeyboardMode = HID_KEYBOARD_SCAN_CODE_SET;
  218. data->Attributes.NumberOfFunctionKeys = HID_KEYBOARD_NUMBER_OF_FUNCTION_KEYS;
  219. data->Attributes.NumberOfIndicators = HID_KEYBOARD_NUMBER_OF_INDICATORS;
  220. data->Attributes.NumberOfKeysTotal = HID_KEYBOARD_NUMBER_OF_KEYS_TOTAL;
  221. data->Attributes.InputDataQueueLength = 1;
  222. data->Attributes.KeyRepeatMinimum.UnitId = data->UnitId;
  223. data->Attributes.KeyRepeatMinimum.Rate = HID_KEYBOARD_TYPEMATIC_RATE_MINIMUM;
  224. data->Attributes.KeyRepeatMinimum.Delay = HID_KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
  225. data->Attributes.KeyRepeatMaximum.UnitId = data->UnitId;
  226. data->Attributes.KeyRepeatMaximum.Rate = HID_KEYBOARD_TYPEMATIC_RATE_MAXIMUM;
  227. data->Attributes.KeyRepeatMaximum.Delay = HID_KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
  228. //
  229. // Initialize the keyboard indicators structure. [DAN]
  230. //
  231. data->Indicators.UnitId = data->UnitId;
  232. data->Indicators.LedFlags = 0;
  233. //
  234. // Initialize the keyboard typematic info structure. [DAN]
  235. //
  236. data->Typematic.UnitId = data->UnitId;
  237. data->Typematic.Rate = HID_KEYBOARD_TYPEMATIC_RATE_DEFAULT;
  238. data->Typematic.Delay = HID_KEYBOARD_TYPEMATIC_DELAY_DEFAULT;
  239. //
  240. // Initialize private typematic information. [DAN]
  241. //
  242. KeInitializeDpc (&data->AutoRepeatDPC, KbdHid_AutoRepeat, data);
  243. KeInitializeTimer (&data->AutoRepeatTimer);
  244. data->AutoRepeatRate = 1000 / HID_KEYBOARD_TYPEMATIC_RATE_DEFAULT; //ms
  245. data->AutoRepeatDelay.LowPart = -HID_KEYBOARD_TYPEMATIC_DELAY_DEFAULT * 10000;
  246. //100ns
  247. data->AutoRepeatDelay.HighPart = -1;
  248. #if KEYBOARD_HW_CHATTERY_FIX // [DAN]
  249. //
  250. // Initialize StartRead-initiator DPC.
  251. //
  252. KeInitializeDpc (&data->InitiateStartReadDPC,
  253. KbdHid_InitiateStartRead,
  254. data);
  255. KeInitializeTimer (&data->InitiateStartReadTimer);
  256. data->InitiateStartReadDelay.QuadPart = -DEFAULT_START_READ_DELAY;
  257. data->InitiateStartReadUserNotified = FALSE;
  258. #endif
  259. state.DeviceState = PowerDeviceD0;
  260. PoSetPowerState (device, DevicePowerState, state);
  261. data->WmiLibInfo.GuidCount = sizeof (KbdHid_WmiGuidList) /
  262. sizeof (WMIGUIDREGINFO);
  263. data->WmiLibInfo.GuidList = KbdHid_WmiGuidList;
  264. data->WmiLibInfo.QueryWmiRegInfo = KbdHid_QueryWmiRegInfo;
  265. data->WmiLibInfo.QueryWmiDataBlock = KbdHid_QueryWmiDataBlock;
  266. data->WmiLibInfo.SetWmiDataBlock = KbdHid_SetWmiDataBlock;
  267. data->WmiLibInfo.SetWmiDataItem = KbdHid_SetWmiDataItem;
  268. data->WmiLibInfo.ExecuteWmiMethod = NULL;
  269. data->WmiLibInfo.WmiFunctionControl = NULL;
  270. device->Flags |= DO_POWER_PAGABLE;
  271. device->Flags &= ~DO_DEVICE_INITIALIZING;
  272. return status;
  273. }
  274. NTSTATUS
  275. KbdHid_StartDevice (
  276. IN PDEVICE_EXTENSION Data
  277. )
  278. /*++
  279. Routine Description:
  280. Arguments:
  281. Return Value:
  282. NTSTATUS result code.
  283. --*/
  284. {
  285. HIDP_CAPS caps; // the capabilities of the found hid device
  286. HID_COLLECTION_INFORMATION info;
  287. NTSTATUS status = STATUS_SUCCESS;
  288. PHIDP_PREPARSED_DATA preparsedData = NULL;
  289. PHID_EXTENSION hid = NULL;
  290. ULONG length, usageListLength, inputBufferLength;
  291. ULONG maxUsages;
  292. PCHAR buffer;
  293. HANDLE devInstRegKey;
  294. ULONG tmp;
  295. PAGED_CODE ();
  296. Print (DBG_PNP_TRACE, ("enter START Device \n"));
  297. //
  298. // Check the registry for any usage mapping information
  299. // for this particular keyboard.
  300. //
  301. // Note: Need to call this after devnode created
  302. // (after START_DEVICE completes).
  303. // For raw devices, this will fail on the first start
  304. // (b/c devnode not there yet)
  305. // but succeed on the second start.
  306. //
  307. LoadKeyboardUsageMappingList (Data);
  308. //
  309. // Retrieve the capabilities of this hid device
  310. // IOCTL_HID_GET_COLLECTION_INFORMATION fills in HID_COLLECTION_INFORMATION.
  311. // we are interested in the Descriptor Size, which tells us how big a
  312. // buffer to allocate for the preparsed data.
  313. //
  314. if (!NT_SUCCESS (status = KbdHid_CallHidClass (
  315. Data,
  316. IOCTL_HID_GET_COLLECTION_INFORMATION,
  317. 0, 0, // no input
  318. &info, sizeof (info)))) {
  319. goto KbdHid_StartDeviceReject;
  320. }
  321. //
  322. // Allocate memory to hold the preparsed data.
  323. //
  324. preparsedData = (PHIDP_PREPARSED_DATA)
  325. ExAllocatePool (NonPagedPool, info.DescriptorSize);
  326. if (!preparsedData) {
  327. status = STATUS_INSUFFICIENT_RESOURCES;
  328. goto KbdHid_StartDeviceReject;
  329. }
  330. //
  331. // Retrieve that information.
  332. //
  333. if (!NT_SUCCESS (status = KbdHid_CallHidClass (
  334. Data,
  335. IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
  336. 0, 0, // no input
  337. preparsedData, info.DescriptorSize))) {
  338. goto KbdHid_StartDeviceReject;
  339. }
  340. //
  341. // Call the parser to determine the capabilites of this HID device.
  342. //
  343. if (!NT_SUCCESS (status = HidP_GetCaps (preparsedData, &caps))) {
  344. goto KbdHid_StartDeviceReject;
  345. }
  346. //
  347. // Set the number of buttons for this keyboard.
  348. // Note: we are actually reading here the total number of independant
  349. // chanels on the device. But that should be satisfactory for a keyboard.
  350. //
  351. Data->Attributes.NumberOfKeysTotal = caps.NumberInputDataIndices;
  352. //
  353. // look for any device parameters.
  354. //
  355. status = IoOpenDeviceRegistryKey (Data->PDO,
  356. PLUGPLAY_REGKEY_DEVICE,
  357. STANDARD_RIGHTS_ALL,
  358. &devInstRegKey);
  359. if (NT_SUCCESS (status)) {
  360. status = KbdHid_QueryDeviceKey (devInstRegKey,
  361. KEYBOARD_TYPE_OVERRIDE,
  362. &tmp,
  363. sizeof (tmp));
  364. if (NT_SUCCESS (status)) {
  365. Data->Attributes.KeyboardIdentifier.Type = (UCHAR) tmp;
  366. Data->IdEx.Type = tmp;
  367. }
  368. status = KbdHid_QueryDeviceKey (devInstRegKey,
  369. KEYBOARD_SUBTYPE_OVERRIDE,
  370. &tmp,
  371. sizeof (tmp));
  372. if (NT_SUCCESS (status)) {
  373. Data->Attributes.KeyboardIdentifier.Subtype = (UCHAR) tmp;
  374. Data->IdEx.Subtype = tmp;
  375. }
  376. status = KbdHid_QueryDeviceKey (devInstRegKey,
  377. KEYBOARD_NUMBER_TOTAL_KEYS_OVERRIDE,
  378. &tmp,
  379. sizeof (tmp));
  380. if (NT_SUCCESS (status)) {
  381. Data->Attributes.NumberOfKeysTotal = (USHORT) tmp;
  382. }
  383. status = KbdHid_QueryDeviceKey (devInstRegKey,
  384. KEYBOARD_NUMBER_FUNCTION_KEYS_OVERRIDE,
  385. &tmp,
  386. sizeof (tmp));
  387. if (NT_SUCCESS (status)) {
  388. Data->Attributes.NumberOfFunctionKeys = (USHORT) tmp;
  389. }
  390. status = KbdHid_QueryDeviceKey (devInstRegKey,
  391. KEYBOARD_NUMBER_INDICATORS_OVERRIDE,
  392. &tmp,
  393. sizeof (tmp));
  394. if (NT_SUCCESS (status)) {
  395. Data->Attributes.NumberOfIndicators = (USHORT) tmp;
  396. }
  397. ZwClose (devInstRegKey);
  398. if (!NT_SUCCESS (status)) {
  399. status = STATUS_SUCCESS;
  400. }
  401. }
  402. //
  403. // Note: here we might also want to check the button and value capabilities
  404. // of the device as well.
  405. //
  406. // Then let's use it.
  407. //
  408. //
  409. // a buffer length to allow an Input buffer, output buffer, feature buffer,
  410. // and the total number of usages that can be returned from a read packet.
  411. //
  412. maxUsages = HidP_MaxUsageListLength (
  413. HidP_Input,
  414. HID_USAGE_PAGE_KEYBOARD,
  415. preparsedData);
  416. //
  417. // Create space in the device extension for the buffer storage when working
  418. // with this HID device.
  419. //
  420. // We need four buffers to hold the button codes (length returned from
  421. // HidP_MaxUsageListLength) this will hold the current list of usages,
  422. // the previous list of usages, the ``Make'' and the ``Break'' lists.
  423. // We also need a place to put the input, output, and feature report
  424. // buffers.
  425. //
  426. if (maxUsages > (MAXULONG / sizeof(USAGE_AND_PAGE) )) {
  427. status = STATUS_UNSUCCESSFUL;
  428. goto KbdHid_StartDeviceReject;
  429. }
  430. usageListLength = ALIGNPTRLEN(maxUsages * sizeof (USAGE_AND_PAGE));
  431. inputBufferLength = ALIGNPTRLEN(caps.InputReportByteLength);
  432. if ((MAXULONG - inputBufferLength < sizeof(HID_EXTENSION)) ||
  433. ((MAXULONG - inputBufferLength - sizeof(HID_EXTENSION))/ 6 < usageListLength)) {
  434. status = STATUS_UNSUCCESSFUL;
  435. goto KbdHid_StartDeviceReject;
  436. }
  437. length = (6 * usageListLength)
  438. + inputBufferLength
  439. + sizeof (HID_EXTENSION);
  440. Data->HidExtension = hid = ExAllocatePool (NonPagedPool, length);
  441. if (!hid) {
  442. status = STATUS_INSUFFICIENT_RESOURCES;
  443. goto KbdHid_StartDeviceReject;
  444. }
  445. RtlZeroMemory (hid, length);
  446. //
  447. // Initialize the fields.
  448. //
  449. hid->Ppd = preparsedData;
  450. hid->Caps = caps;
  451. hid->MaxUsages = maxUsages;
  452. // hid->ModifierState.ul = 0;
  453. hid->InputBuffer = buffer = hid->Buffer;
  454. hid->PreviousUsageList = (PUSAGE_AND_PAGE) (buffer += inputBufferLength);
  455. hid->CurrentUsageList = (PUSAGE_AND_PAGE) (buffer += usageListLength);
  456. hid->BreakUsageList = (PUSAGE_AND_PAGE) (buffer += usageListLength);
  457. hid->MakeUsageList = (PUSAGE_AND_PAGE) (buffer += usageListLength);
  458. hid->OldMakeUsageList = (PUSAGE_AND_PAGE) (buffer += usageListLength);
  459. hid->ScrapBreakUsageList = (PUSAGE_AND_PAGE) (buffer + usageListLength);
  460. //
  461. // Create the MDLs
  462. // HidClass uses direct IO so you need MDLs
  463. //
  464. hid->InputMdl = IoAllocateMdl (hid->InputBuffer, // The virtual address
  465. caps.InputReportByteLength, // length
  466. FALSE, // No associated IRP => not secondary
  467. FALSE, // No quota charge
  468. 0); // No associated IRP
  469. if (NULL == hid->InputMdl) {
  470. status = STATUS_INSUFFICIENT_RESOURCES;
  471. goto KbdHid_StartDeviceReject;
  472. }
  473. MmBuildMdlForNonPagedPool (hid->InputMdl); // Build this MDL.
  474. return status;
  475. KbdHid_StartDeviceReject:
  476. if (preparsedData) {
  477. // no need to set hid->Ppd to NULL becuase we will be freeing it as well
  478. ExFreePool (preparsedData);
  479. }
  480. if (hid) {
  481. if (hid->InputMdl) {
  482. IoFreeMdl (hid->InputMdl);
  483. }
  484. ExFreePool (hid);
  485. Data->HidExtension = NULL;
  486. }
  487. return status;
  488. }
  489. NTSTATUS
  490. KbdHid_PnP (
  491. IN PDEVICE_OBJECT DeviceObject,
  492. IN PIRP Irp
  493. )
  494. /*++
  495. Routine Description:
  496. The plug and play dispatch routines.
  497. Most of these this filter driver will completely ignore.
  498. In all cases it must pass on the IRP to the lower driver.
  499. Arguments:
  500. DeviceObject - pointer to a device object.
  501. Irp - pointer to an I/O Request Packet.
  502. Return Value:
  503. NT status code
  504. --*/
  505. {
  506. PDEVICE_EXTENSION data;
  507. PHID_EXTENSION hid;
  508. PIO_STACK_LOCATION stack;
  509. NTSTATUS status;
  510. ULONG i, j;
  511. PDEVICE_EXTENSION * classDataList;
  512. LARGE_INTEGER time;
  513. PAGED_CODE ();
  514. data = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  515. stack = IoGetCurrentIrpStackLocation (Irp);
  516. hid = data->HidExtension;
  517. status = IoAcquireRemoveLock (&data->RemoveLock, Irp);
  518. if (!NT_SUCCESS (status)) {
  519. //
  520. // Someone gave us a pnp irp after a remove. Unthinkable!
  521. //
  522. ASSERT (FALSE);
  523. Irp->IoStatus.Information = 0;
  524. Irp->IoStatus.Status = status;
  525. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  526. return status;
  527. }
  528. Print(DBG_PNP_TRACE, ("PNP: Minor code = %x.", stack->MinorFunction));
  529. switch (stack->MinorFunction) {
  530. case IRP_MN_START_DEVICE:
  531. if (data->Started) {
  532. Print(DBG_PNP_INFO, ("PNP: Device already started." ));
  533. status = STATUS_SUCCESS;
  534. Irp->IoStatus.Status = status;
  535. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  536. break;
  537. }
  538. //
  539. // The device is starting.
  540. //
  541. // We cannot touch the device (send it any non pnp irps) until a
  542. // start device has been passed down to the lower drivers.
  543. //
  544. IoCopyCurrentIrpStackLocationToNext (Irp);
  545. KeInitializeEvent(&data->StartEvent, NotificationEvent, FALSE);
  546. IoSetCompletionRoutine (Irp,
  547. KbdHid_PnPComplete,
  548. data,
  549. TRUE,
  550. TRUE,
  551. TRUE); // No need for Cancel
  552. Irp->IoStatus.Status = STATUS_SUCCESS;
  553. status = IoCallDriver (data->TopOfStack, Irp);
  554. if (STATUS_PENDING == status) {
  555. KeWaitForSingleObject(
  556. &data->StartEvent,
  557. Executive, // Waiting for reason of a driver
  558. KernelMode, // Waiting in kernel mode
  559. FALSE, // No allert
  560. NULL); // No timeout
  561. }
  562. if (NT_SUCCESS (status) && NT_SUCCESS (Irp->IoStatus.Status)) {
  563. //
  564. // As we are successfully now back from our start device
  565. // we can do work.
  566. //
  567. if (!data->Initialized) {
  568. status = KbdHid_StartDevice (data);
  569. if (NT_SUCCESS (status)) {
  570. IoWMIRegistrationControl(DeviceObject,
  571. WMIREG_ACTION_REGISTER
  572. );
  573. data->Started = TRUE;
  574. data->Initialized = TRUE;
  575. }
  576. } else {
  577. data->Started = TRUE;
  578. }
  579. }
  580. //
  581. // We must now complete the IRP, since we stopped it in the
  582. // completetion routine with MORE_PROCESSING_REQUIRED.
  583. //
  584. Irp->IoStatus.Status = status;
  585. Irp->IoStatus.Information = 0;
  586. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  587. break;
  588. case IRP_MN_STOP_DEVICE:
  589. //
  590. // After the start IRP has been sent to the lower driver object, the
  591. // bus may NOT send any more IRPS down ``touch'' until another START
  592. // has occured.
  593. // What ever access is required must be done before the Irp is passed
  594. // on.
  595. //
  596. if (data->Started) {
  597. //
  598. // Do what ever
  599. //
  600. }
  601. //
  602. // We don't need a completion routine so fire and forget.
  603. //
  604. // Set the current stack location to the next stack location and
  605. // call the next device object.
  606. //
  607. //
  608. // Stop Device touching the hardware MouStopDevice(data, TRUE);
  609. //
  610. data->Started = FALSE;
  611. Irp->IoStatus.Status = STATUS_SUCCESS;
  612. IoSkipCurrentIrpStackLocation (Irp);
  613. status = IoCallDriver (data->TopOfStack, Irp);
  614. break;
  615. case IRP_MN_REMOVE_DEVICE:
  616. //
  617. // The PlugPlay system has detected the removal of this device. We
  618. // have no choise but to detach and delete the device objecct.
  619. // (If we wanted to express and interest in preventing this removal,
  620. // we should have filtered the query remove and query stop routines.)
  621. //
  622. // Note! we might receive a remove WITHOUT first receiving a stop.
  623. // ASSERT (!usbData->Removed);
  624. Print (DBG_PNP_TRACE, ("enter RemoveDevice \n"));
  625. IoWMIRegistrationControl(data->Self,
  626. WMIREG_ACTION_DEREGISTER
  627. );
  628. if (data->Started) {
  629. // Stop the device without touching the hardware.
  630. // MouStopDevice(data, FALSE);
  631. }
  632. //
  633. // Here if we had any outstanding requests in a personal queue we should
  634. // complete them all now.
  635. //
  636. // Note, the device could be GONE so we cannot send it any non-
  637. // PNP IRPS.
  638. //
  639. time = data->AutoRepeatDelay;
  640. KeCancelTimer (&data->AutoRepeatTimer);
  641. #if KEYBOARD_HW_CHATTERY_FIX
  642. KeCancelTimer (&data->InitiateStartReadTimer);
  643. //
  644. // NB the time is a negative (relative) number;
  645. //
  646. if (data->InitiateStartReadDelay.QuadPart < time.QuadPart) {
  647. time = data->InitiateStartReadDelay;
  648. }
  649. #endif
  650. KeDelayExecutionThread (KernelMode, FALSE, &time);
  651. //
  652. // Cancel our read IRP. [DAN]
  653. // Note - waiting is only really necessary on 98, where pnp doesn't
  654. // make sure all handles are closed before sending the remove.
  655. //
  656. data->ShuttingDown = TRUE;
  657. KeWaitForSingleObject (&data->ReadSentEvent,
  658. Executive,
  659. KernelMode,
  660. FALSE,
  661. NULL
  662. );
  663. IoCancelIrp (data->ReadIrp);
  664. //
  665. // Send on the remove IRP
  666. //
  667. Irp->IoStatus.Status = STATUS_SUCCESS;
  668. IoSkipCurrentIrpStackLocation (Irp);
  669. status = IoCallDriver (data->TopOfStack, Irp);
  670. //
  671. // Wait for the remove lock to free.
  672. //
  673. IoReleaseRemoveLockAndWait (&data->RemoveLock, Irp);
  674. //
  675. // Free the associated memory.
  676. //
  677. IoFreeIrp (data->ReadIrp);
  678. if (hid) {
  679. //
  680. // If we are removed without being started then we will have
  681. // no hid extension
  682. //
  683. ExFreePool (hid->Ppd);
  684. IoFreeMdl (hid->InputMdl);
  685. ExFreePool (hid);
  686. }
  687. FreeKeyboardUsageMappingList(data);
  688. IoDetachDevice (data->TopOfStack);
  689. IoDeleteDevice (data->Self);
  690. return status;
  691. case IRP_MN_SURPRISE_REMOVAL:
  692. case IRP_MN_QUERY_REMOVE_DEVICE:
  693. case IRP_MN_CANCEL_REMOVE_DEVICE:
  694. case IRP_MN_QUERY_STOP_DEVICE:
  695. case IRP_MN_CANCEL_STOP_DEVICE:
  696. //
  697. // These IRPs have to have their status changed from
  698. // STATUS_NOT_SUPPORTED b4 passing them down.
  699. //
  700. Irp->IoStatus.Status = STATUS_SUCCESS;
  701. case IRP_MN_QUERY_DEVICE_RELATIONS:
  702. case IRP_MN_QUERY_INTERFACE:
  703. case IRP_MN_QUERY_CAPABILITIES:
  704. case IRP_MN_QUERY_RESOURCES:
  705. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  706. case IRP_MN_READ_CONFIG:
  707. case IRP_MN_WRITE_CONFIG:
  708. case IRP_MN_EJECT:
  709. case IRP_MN_SET_LOCK:
  710. case IRP_MN_QUERY_ID:
  711. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  712. default:
  713. //
  714. // Here the filter driver might modify the behavior of these IRPS
  715. // Please see PlugPlay documentation for use of these IRPs.
  716. //
  717. IoSkipCurrentIrpStackLocation (Irp);
  718. status = IoCallDriver (data->TopOfStack, Irp);
  719. break;
  720. }
  721. IoReleaseRemoveLock (&data->RemoveLock, Irp);
  722. return status;
  723. }
  724. NTSTATUS
  725. KbdHid_PnPComplete (
  726. IN PDEVICE_OBJECT DeviceObject,
  727. IN PIRP Irp,
  728. IN PVOID Context
  729. )
  730. /*++
  731. Routine Description:
  732. The pnp IRP is in the process of completing.
  733. signal
  734. Arguments:
  735. Context set to the device object in question.
  736. --*/
  737. {
  738. PIO_STACK_LOCATION stack;
  739. PDEVICE_EXTENSION data;
  740. NTSTATUS status;
  741. UNREFERENCED_PARAMETER (DeviceObject);
  742. status = STATUS_SUCCESS;
  743. data = (PDEVICE_EXTENSION) Context;
  744. stack = IoGetCurrentIrpStackLocation (Irp);
  745. if (Irp->PendingReturned) {
  746. IoMarkIrpPending( Irp );
  747. }
  748. switch (stack->MajorFunction) {
  749. case IRP_MJ_PNP:
  750. switch (stack->MinorFunction) {
  751. case IRP_MN_START_DEVICE:
  752. KeSetEvent (&data->StartEvent, 0, FALSE);
  753. //
  754. // Take the IRP back so that we can continue using it during
  755. // the IRP_MN_START_DEVICE dispatch routine.
  756. // NB: we will have to call IoCompleteRequest
  757. //
  758. return STATUS_MORE_PROCESSING_REQUIRED;
  759. default:
  760. break;
  761. }
  762. break;
  763. case IRP_MJ_POWER:
  764. default:
  765. break;
  766. }
  767. return status;
  768. }
  769. NTSTATUS
  770. KbdHid_Power (
  771. IN PDEVICE_OBJECT DeviceObject,
  772. IN PIRP Irp
  773. )
  774. {
  775. PIO_STACK_LOCATION stack;
  776. NTSTATUS status;
  777. PDEVICE_EXTENSION data;
  778. POWER_STATE powerState;
  779. POWER_STATE_TYPE powerType;
  780. Print(DBG_POWER_TRACE, ("Power Enter." ));
  781. data = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  782. stack = IoGetCurrentIrpStackLocation (Irp);
  783. powerType = stack->Parameters.Power.Type;
  784. powerState = stack->Parameters.Power.State;
  785. status = IoAcquireRemoveLock (&data->RemoveLock, Irp);
  786. if (!NT_SUCCESS (status)) {
  787. PoStartNextPowerIrp (Irp);
  788. Irp->IoStatus.Status = status;
  789. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  790. return status;
  791. }
  792. switch (stack->MinorFunction) {
  793. case IRP_MN_SET_POWER:
  794. Print(DBG_POWER_INFO, ("Power Setting %s state to %d\n",
  795. ((powerType == SystemPowerState) ? "System"
  796. : "Device"),
  797. powerState.SystemState));
  798. break;
  799. case IRP_MN_QUERY_POWER:
  800. Print (DBG_POWER_INFO, ("Power query %s status to %d\n",
  801. ((powerType == SystemPowerState) ? "System"
  802. : "Device"),
  803. powerState.SystemState));
  804. break;
  805. default:
  806. Print (DBG_POWER_ERROR, ("Power minor (0x%x) no known\n",
  807. stack->MinorFunction));
  808. }
  809. PoStartNextPowerIrp (Irp);
  810. IoSkipCurrentIrpStackLocation (Irp);
  811. status = PoCallDriver (data->TopOfStack, Irp);
  812. IoReleaseRemoveLock (&data->RemoveLock, Irp);
  813. return status;
  814. }