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.

914 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract: Human Input Device (HID) minidriver for Infrared (IR) devices
  6. The HID IR Minidriver (HidIr) provides an abstraction layer for the
  7. HID Class to talk to HID IR devices.
  8. Author:
  9. jsenior
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. //
  16. // The HID descriptor has some basic device info and tells how long the report
  17. // descriptor is.
  18. //
  19. HIDIR_DESCRIPTOR HidIrHidDescriptor = {
  20. 0x09, // length of HID descriptor
  21. 0x21, // descriptor type == HID
  22. 0x0100, // hid spec release
  23. 0x00, // country code == Not Specified
  24. 0x01, // number of HID class descriptors
  25. 0x22, // report descriptor type
  26. 0 // total length of report descriptor (to be set)
  27. };
  28. //
  29. // The report descriptor completely lays out what read and write packets will
  30. // look like and indicates what the semantics are for each field. This here is
  31. // what the report descriptor looks like in a broken out format. This is
  32. // actually retrieved from the registry (device key).
  33. //
  34. /*
  35. HID_REPORT_DESCRIPTOR HidIrReportDescriptor[] = {
  36. // Keyboard
  37. 0x05, 0x01, // Usage Page (Generic Desktop),
  38. 0x09, 0x06, // Usage (Keyboard),
  39. 0xA1, 0x01, // Collection (Application),
  40. 0x85, 0x01, // Report Id (1)
  41. 0x05, 0x07, // usage page key codes
  42. 0x19, 0xe0, // usage min left control
  43. 0x29, 0xe7, // usage max keyboard right gui
  44. 0x75, 0x01, // report size 1
  45. 0x95, 0x08, // report count 8
  46. 0x81, 0x02, // input (Variable)
  47. 0x19, 0x00, // usage min 0
  48. 0x29, 0x91, // usage max 91
  49. 0x26, 0xff, 0x00, // logical max 0xff
  50. 0x75, 0x08, // report size 8
  51. 0x95, 0x01, // report count 1
  52. 0x81, 0x00, // Input (Data, Array),
  53. 0xC0, // End Collection
  54. // Consumer Controls
  55. 0x05, 0x0c, // Usage Page (Consumer Controls),
  56. 0x09, 0x01, // Usage (Consumer Control),
  57. 0xA1, 0x01, // Collection (Application),
  58. 0x85, 0x02, // Report Id (2)
  59. 0x19, 0x00, // Usage Minimum (0),
  60. 0x2a, 0x3c, 0x02, // Usage Maximum (23c)
  61. 0x15, 0x00, // Logical Minimum (0),
  62. 0x26, 0x3c, 0x02, // Logical Maximum (23c)
  63. 0x95, 0x01, // Report Count (1),
  64. 0x75, 0x10, // Report Size (16),
  65. 0x81, 0x00, // Input (Data, Array),
  66. 0xC0, // End Collection
  67. // Standby button
  68. 0x05, 0x01, // Usage Page (Generic Desktop),
  69. 0x09, 0x80, // Usage (System Control),
  70. 0xa1, 0x01, // Collection (Application),
  71. 0x85, 0x03, // Report Id (3)
  72. 0x19, 0x81, // Usage Minimum (0x81),
  73. 0x29, 0x83, // Usage Maximum (0x83),
  74. 0x25, 0x01, // Logical Maximum(1),
  75. 0x75, 0x01, // Report Size (1),
  76. 0x95, 0x03, // Report Count (3),
  77. 0x81, 0x02, // Input
  78. 0x95, 0x05, // Report Count (5),
  79. 0x81, 0x01, // Input (Constant),
  80. 0xc0 // End Collection
  81. };
  82. //
  83. // The mapping table translates from what the irbus driver gives us into a
  84. // HID report to return to hidclass. The hid report is of the correct length
  85. // according to what the registry told us (device key).
  86. //
  87. USAGE_TABLE_ENTRY HidIrMappingTable[] = {
  88. { 0x00001808, {0x01,0x00,0x1e}}, // 1
  89. { 0x00001828, {0x01,0x00,0x1f}}, // 2
  90. { 0x00001818, {0x01,0x00,0x20}}, // 3
  91. { 0x0000182b, {0x01,0x02,0x20}}, // # (shift+3)
  92. { 0x00001804, {0x01,0x00,0x21}}, // 4
  93. { 0x00001824, {0x01,0x00,0x22}}, // 5
  94. { 0x00001814, {0x01,0x00,0x23}}, // 6
  95. { 0x0000180c, {0x01,0x00,0x24}}, // 7
  96. { 0x0000182c, {0x01,0x00,0x25}}, // 8
  97. { 0x00000001, {0x01,0x00,0x55}}, // Numpad *
  98. { 0x0000181c, {0x01,0x00,0x26}}, // 9
  99. { 0x00001822, {0x01,0x00,0x27}}, // 0
  100. { 0x00001836, {0x01,0x00,0x28}}, // return
  101. { 0x0000000B, {0x01,0x04,0x29}}, // alt+escape
  102. { 0x0000182b, {0x01,0x00,0x2a}}, // delete (backspace)
  103. { 0x00001806, {0x01,0x00,0x2b}}, // tab
  104. { 0x0000180e, {0x01,0x02,0x2b}}, // shift+tab
  105. { 0x00001826, {0x01,0x00,0x4b}}, // page up
  106. { 0x0000182e, {0x01,0x00,0x4e}}, // page down
  107. { 0x0000181e, {0x01,0x00,0x51}}, // down
  108. { 0x00001816, {0x01,0x00,0x52}}, // up
  109. { 0x0000181a, {0x01,0x00,0x65}}, // context
  110. { 0x00001813, {0x02,0x09,0x02}}, // AC Properties
  111. { 0x00001800, {0x02,0x24,0x02}}, // AC Back
  112. { 0x0000180a, {0x02,0x2a,0x02}}, // AC favorites
  113. { 0x00001823, {0x02,0x30,0x02}}, // AC full screen
  114. { 0x00001830, {0x02,0xb0,0x00}}, // AC Media play
  115. { 0x00001830, {0x02,0xb1,0x00}}, // AC Media pause
  116. { 0x0000183e, {0x02,0xb2,0x00}}, // AC Media record
  117. { 0x00001829, {0x02,0xb3,0x00}}, // AC FF
  118. { 0x00001838, {0x02,0xb4,0x00}}, // AC RW
  119. { 0x00001831, {0x02,0xb5,0x00}}, // AC Media next track
  120. { 0x00001811, {0x02,0xb6,0x00}}, // AC Media previous track
  121. { 0x00001821, {0x02,0xb7,0x00}}, // AC Media Stop
  122. { 0x0000000B, {0x02,0xe9,0x00}}, // AC volume up
  123. { 0x0000000B, {0x02,0xea,0x00}}, // AC volume down
  124. { 0x0000000B, {0x02,0xe2,0x00}}, // AC volume mute
  125. { 0x00001803, {0x02,0x8d,0x00}}, // AC select program guide
  126. { 0x00001801, {0x02,0x9c,0x00}}, // AC channel up
  127. { 0x0000183c, {0x02,0x9d,0x00}}}; // AC channel down
  128. */
  129. NTSTATUS
  130. HidIrRemoveDevice(
  131. IN PDEVICE_OBJECT DeviceObject
  132. );
  133. NTSTATUS
  134. HidIrCleanupDevice(
  135. IN PDEVICE_OBJECT DeviceObject
  136. );
  137. NTSTATUS
  138. HidIrStopDevice(
  139. IN PDEVICE_OBJECT DeviceObject
  140. );
  141. NTSTATUS
  142. HidIrStopCompletion(
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN PIRP Irp
  145. );
  146. NTSTATUS
  147. HidIrStartCompletion(
  148. IN PDEVICE_OBJECT DeviceObject,
  149. IN PIRP Irp
  150. );
  151. NTSTATUS
  152. HidIrInitDevice(
  153. IN PDEVICE_OBJECT DeviceObject
  154. );
  155. NTSTATUS
  156. HidIrStartDevice(
  157. IN PDEVICE_OBJECT DeviceObject
  158. );
  159. #ifdef ALLOC_PRAGMA
  160. // NOTE: Every single function in this file is pageable.
  161. #pragma alloc_text(PAGE, HidIrStartDevice)
  162. #pragma alloc_text(PAGE, HidIrPnP)
  163. #pragma alloc_text(PAGE, HidIrRemoveDevice)
  164. #pragma alloc_text(PAGE, HidIrCleanupDevice)
  165. #pragma alloc_text(PAGE, HidIrStopDevice)
  166. #pragma alloc_text(PAGE, HidIrStopCompletion)
  167. #pragma alloc_text(PAGE, HidIrStartCompletion)
  168. #pragma alloc_text(PAGE, HidIrInitDevice)
  169. #endif
  170. NTSTATUS
  171. HidIrStartDevice(
  172. IN PDEVICE_OBJECT DeviceObject
  173. )
  174. /*++
  175. Routine Description:
  176. Begins initialization a given instance of a HID device. Work done here occurs before
  177. the parent node gets to do anything.
  178. Arguments:
  179. DeviceObject - pointer to the device object for this instance.
  180. Return Value:
  181. NT status code
  182. --*/
  183. {
  184. PHIDIR_EXTENSION devExt;
  185. NTSTATUS ntStatus = STATUS_SUCCESS;
  186. ULONG oldDeviceState;
  187. PAGED_CODE();
  188. // Get a pointer to the device extension
  189. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  190. HidIrKdPrint((3, "HidIrStartDevice devExt = %x", devExt));
  191. // Start the device
  192. oldDeviceState = devExt->DeviceState;
  193. devExt->DeviceState = DEVICE_STATE_STARTING;
  194. KeResetEvent(&devExt->AllRequestsCompleteEvent);
  195. if ((oldDeviceState == DEVICE_STATE_STOPPING) ||
  196. (oldDeviceState == DEVICE_STATE_STOPPED) ||
  197. (oldDeviceState == DEVICE_STATE_REMOVING)){
  198. /*
  199. * We did an extra decrement when the device was stopped.
  200. * Now that we're restarting, we need to bump it back to zero.
  201. */
  202. NTSTATUS incStat = HidIrIncrementPendingRequestCount(devExt);
  203. ASSERT(NT_SUCCESS(incStat));
  204. ASSERT(devExt->NumPendingRequests == 0);
  205. HidIrKdPrint((2, "Got start-after-stop; re-incremented pendingRequestCount"));
  206. }
  207. HidIrKdPrint((3, "HidIrStartDevice Exit = %x", ntStatus));
  208. return ntStatus;
  209. }
  210. NTSTATUS
  211. HidIrQueryDeviceKey (
  212. IN HANDLE Handle,
  213. IN PWCHAR ValueNameString,
  214. OUT PVOID *Data,
  215. OUT ULONG *DataLength
  216. )
  217. {
  218. NTSTATUS status;
  219. UNICODE_STRING valueName;
  220. ULONG length;
  221. KEY_VALUE_FULL_INFORMATION info;
  222. ASSERT(Data);
  223. ASSERT(DataLength);
  224. // Init
  225. *Data = NULL;
  226. *DataLength = 0;
  227. RtlInitUnicodeString (&valueName, ValueNameString);
  228. status = ZwQueryValueKey (Handle,
  229. &valueName,
  230. KeyValueFullInformation,
  231. &info,
  232. sizeof(info),
  233. &length);
  234. if (STATUS_BUFFER_TOO_SMALL == status ||
  235. STATUS_BUFFER_OVERFLOW == status) {
  236. PKEY_VALUE_FULL_INFORMATION fullInfo;
  237. fullInfo = ALLOCATEPOOL (PagedPool, length);
  238. if (fullInfo) {
  239. status = ZwQueryValueKey (Handle,
  240. &valueName,
  241. KeyValueFullInformation,
  242. fullInfo,
  243. length,
  244. &length);
  245. if (NT_SUCCESS(status)) {
  246. *DataLength = fullInfo->DataLength;
  247. *Data = ALLOCATEPOOL (NonPagedPool, fullInfo->DataLength);
  248. if (*Data) {
  249. RtlCopyMemory (*Data,
  250. ((PUCHAR) fullInfo) + fullInfo->DataOffset,
  251. fullInfo->DataLength);
  252. } else {
  253. status = STATUS_INSUFFICIENT_RESOURCES;
  254. }
  255. }
  256. ExFreePool (fullInfo);
  257. } else {
  258. status = STATUS_INSUFFICIENT_RESOURCES;
  259. }
  260. } else if (NT_SUCCESS(status)) {
  261. HIR_TRAP(); // we didn't alloc any space. This is bad.
  262. status = STATUS_UNSUCCESSFUL;
  263. }
  264. return status;
  265. }
  266. #define HIDIR_REPORT_LENGTH L"ReportLength"
  267. #define HIDIR_REPORT_DESCRIPTOR L"ReportDescriptor"
  268. #define HIDIR_MAPPING_TABLE L"ReportMappingTable"
  269. #define HIDIR_VENDOR_ID L"VendorID"
  270. #define HIDIR_PRODUCT_ID L"ProductID"
  271. NTSTATUS
  272. HidIrInitDevice(
  273. IN PDEVICE_OBJECT DeviceObject
  274. )
  275. /*++
  276. Routine Description:
  277. Get the device information and attempt to initialize a configuration
  278. for a device. If we cannot identify this as a valid HID device or
  279. configure the device, our start device function is failed.
  280. Arguments:
  281. DeviceObject - pointer to a device object.
  282. Return Value:
  283. NT status code.
  284. --*/
  285. {
  286. NTSTATUS status = STATUS_SUCCESS;
  287. PHIDIR_EXTENSION devExt;
  288. PHID_DEVICE_EXTENSION hidExtension;
  289. HANDLE devInstRegKey = NULL;
  290. ULONG dataLen;
  291. PAGED_CODE();
  292. HidIrKdPrint((3, "HidIrInitDevice Entry"));
  293. hidExtension = DeviceObject->DeviceExtension;
  294. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  295. devExt->HidDescriptor = HidIrHidDescriptor;
  296. status = IoOpenDeviceRegistryKey (hidExtension->PhysicalDeviceObject,
  297. PLUGPLAY_REGKEY_DEVICE,
  298. STANDARD_RIGHTS_READ,
  299. &devInstRegKey);
  300. if (NT_SUCCESS (status)) {
  301. PULONG reportLength;
  302. status = HidIrQueryDeviceKey (devInstRegKey,
  303. HIDIR_REPORT_LENGTH,
  304. &reportLength,
  305. &dataLen);
  306. if (NT_SUCCESS (status)) {
  307. if (dataLen == sizeof(ULONG)) {
  308. devExt->ReportLength = *reportLength;
  309. } else {
  310. status = STATUS_INVALID_BUFFER_SIZE;
  311. }
  312. ExFreePool(reportLength);
  313. }
  314. }
  315. if (NT_SUCCESS(status)) {
  316. status = HidIrQueryDeviceKey (devInstRegKey,
  317. HIDIR_REPORT_DESCRIPTOR,
  318. &devExt->ReportDescriptor,
  319. &dataLen);
  320. if (NT_SUCCESS(status)) {
  321. ASSERT(dataLen);
  322. devExt->HidDescriptor.DescriptorList[0].wDescriptorLength = (USHORT)dataLen;
  323. }
  324. }
  325. if (NT_SUCCESS(status)) {
  326. PULONG vendorID;
  327. status = HidIrQueryDeviceKey (devInstRegKey,
  328. HIDIR_VENDOR_ID,
  329. &vendorID,
  330. &dataLen);
  331. if (NT_SUCCESS (status)) {
  332. if (dataLen == sizeof(ULONG)) {
  333. devExt->VendorID = (USHORT)*vendorID;
  334. } else {
  335. status = STATUS_INVALID_BUFFER_SIZE;
  336. }
  337. ExFreePool(vendorID);
  338. }
  339. }
  340. if (NT_SUCCESS(status)) {
  341. PULONG productID;
  342. status = HidIrQueryDeviceKey (devInstRegKey,
  343. HIDIR_PRODUCT_ID,
  344. &productID,
  345. &dataLen);
  346. if (NT_SUCCESS (status)) {
  347. if (dataLen == sizeof(ULONG)) {
  348. devExt->ProductID = (USHORT)*productID;
  349. } else {
  350. status = STATUS_INVALID_BUFFER_SIZE;
  351. }
  352. ExFreePool(productID);
  353. }
  354. }
  355. if (NT_SUCCESS (status)) {
  356. PUCHAR mappingTable;
  357. status = HidIrQueryDeviceKey (devInstRegKey,
  358. HIDIR_MAPPING_TABLE,
  359. &mappingTable,
  360. &dataLen);
  361. if (NT_SUCCESS(status)) {
  362. ULONG i;
  363. ULONG entrySize = HIDIR_TABLE_ENTRY_SIZE(devExt->ReportLength);
  364. ASSERT(dataLen > sizeof(ULONG)+devExt->ReportLength); // at least one entry
  365. ASSERT((dataLen % (sizeof(ULONG)+devExt->ReportLength)) == 0); // not malformed data
  366. // This will round down for malformed data.
  367. devExt->NumUsages = dataLen / (sizeof(ULONG)+devExt->ReportLength);
  368. // I have to do all this for 64-bit.
  369. devExt->MappingTable = ALLOCATEPOOL(NonPagedPool, devExt->NumUsages*entrySize);
  370. if (devExt->MappingTable) {
  371. // Fill in the table
  372. for (i = 0; i < devExt->NumUsages; i++) {
  373. RtlCopyMemory(devExt->MappingTable+(entrySize*i),
  374. mappingTable+((sizeof(ULONG)+devExt->ReportLength)*i),
  375. sizeof(ULONG));
  376. RtlCopyMemory(devExt->MappingTable+(entrySize*i)+sizeof(ULONG),
  377. mappingTable+((sizeof(ULONG)+devExt->ReportLength)*i)+sizeof(ULONG),
  378. devExt->ReportLength);
  379. }
  380. } else {
  381. status = STATUS_INSUFFICIENT_RESOURCES;
  382. }
  383. ExFreePool(mappingTable);
  384. }
  385. }
  386. if (devInstRegKey) {
  387. ZwClose(devInstRegKey);
  388. }
  389. if (NT_SUCCESS(status)) {
  390. HIDP_DEVICE_DESC deviceDesc; // 0x30 bytes
  391. // Find the keyboard and standby button collections and their associated report IDs.
  392. ASSERT(!devExt->KeyboardReportIdValid);
  393. if (NT_SUCCESS(HidP_GetCollectionDescription(
  394. devExt->ReportDescriptor,
  395. devExt->HidDescriptor.DescriptorList[0].wDescriptorLength,
  396. NonPagedPool,
  397. &deviceDesc))) {
  398. ULONG i,j;
  399. UCHAR nCollectionKbd, nCollectionStandby;
  400. BOOLEAN foundKbd = FALSE, foundStandby = FALSE;
  401. for (i = 0; i < deviceDesc.CollectionDescLength; i++) {
  402. PHIDP_COLLECTION_DESC collection = &deviceDesc.CollectionDesc[i];
  403. if (collection->UsagePage == HID_USAGE_PAGE_GENERIC &&
  404. (collection->Usage == HID_USAGE_GENERIC_KEYBOARD ||
  405. collection->Usage == HID_USAGE_GENERIC_KEYPAD)) {
  406. // Found the collection, onto the report id!
  407. nCollectionKbd = collection->CollectionNumber;
  408. foundKbd = TRUE;
  409. } else if (collection->UsagePage == HID_USAGE_PAGE_GENERIC &&
  410. collection->Usage == HID_USAGE_GENERIC_SYSTEM_CTL) {
  411. nCollectionStandby = collection->CollectionNumber;
  412. foundStandby = TRUE;
  413. }
  414. }
  415. for (j = 0; j < deviceDesc.ReportIDsLength; j++) {
  416. if (foundKbd && deviceDesc.ReportIDs[j].CollectionNumber == nCollectionKbd) {
  417. // I make the assumption that there is only one report id on this collection.
  418. devExt->KeyboardReportId = deviceDesc.ReportIDs[j].ReportID;
  419. devExt->KeyboardReportIdValid = TRUE;
  420. } else if (foundStandby && deviceDesc.ReportIDs[j].CollectionNumber == nCollectionStandby) {
  421. // I make the assumption that there is only one report id on this collection.
  422. devExt->StandbyReportId = deviceDesc.ReportIDs[j].ReportID;
  423. devExt->StandbyReportIdValid = TRUE;
  424. }
  425. }
  426. HidP_FreeCollectionDescription(&deviceDesc);
  427. }
  428. }
  429. return status;
  430. }
  431. NTSTATUS
  432. HidIrStartCompletion(
  433. IN PDEVICE_OBJECT DeviceObject,
  434. IN PIRP Irp
  435. )
  436. /*++
  437. Routine Description:
  438. Completes initialization a given instance of a HID device. Work done here occurs
  439. after the parent node has done its StartDevice.
  440. Arguments:
  441. DeviceObject - pointer to the device object for this instance.
  442. Return Value:
  443. NT status code
  444. --*/
  445. {
  446. PHIDIR_EXTENSION devExt;
  447. NTSTATUS ntStatus;
  448. PAGED_CODE();
  449. HidIrKdPrint((3, "HidIrStartCompletion Enter"));
  450. //
  451. // Get a pointer to the device extension
  452. //
  453. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  454. devExt->DeviceState = DEVICE_STATE_RUNNING;
  455. HidIrKdPrint((3, "DeviceObject (%x) was started!", DeviceObject));
  456. ntStatus = HidIrInitDevice(DeviceObject);
  457. if(NT_SUCCESS(ntStatus)) {
  458. HidIrKdPrint((3, "DeviceObject (%x) was configured!", DeviceObject));
  459. } else {
  460. HidIrKdPrint((1, "'HIDIR.SYS: DeviceObject (%x) configuration failed!", DeviceObject));
  461. devExt->DeviceState = DEVICE_STATE_STOPPING;
  462. }
  463. HidIrKdPrint((3, "HidIrStartCompletion Exit = %x", ntStatus));
  464. return ntStatus;
  465. }
  466. NTSTATUS
  467. HidIrStopDevice(
  468. IN PDEVICE_OBJECT DeviceObject
  469. )
  470. /*++
  471. Routine Description:
  472. Stops a given instance of a device. Work done here occurs before the parent
  473. does its stop device.
  474. Arguments:
  475. DeviceObject - pointer to the device object.
  476. Return Value:
  477. NT status code
  478. --*/
  479. {
  480. NTSTATUS ntStatus = STATUS_SUCCESS;
  481. PHIDIR_EXTENSION devExt;
  482. PAGED_CODE();
  483. HidIrKdPrint((3, "HidIrStopDevice Enter"));
  484. //
  485. // Get a pointer to the device extension
  486. //
  487. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  488. HidIrKdPrint((3, "DeviceExtension = %x", devExt));
  489. devExt->DeviceState = DEVICE_STATE_STOPPING;
  490. HidIrDecrementPendingRequestCount(devExt);
  491. KeWaitForSingleObject( &devExt->AllRequestsCompleteEvent,
  492. Executive,
  493. KernelMode,
  494. FALSE,
  495. NULL );
  496. //
  497. // Stop the device
  498. //
  499. HidIrKdPrint((3, "HidIrStopDevice = %x", ntStatus));
  500. return ntStatus;
  501. }
  502. VOID
  503. HidIrFreeResources(
  504. PHIDIR_EXTENSION DevExt
  505. )
  506. {
  507. PAGED_CODE();
  508. if (DevExt->ReportDescriptor) {
  509. ExFreePool(DevExt->ReportDescriptor);
  510. DevExt->ReportDescriptor = NULL;
  511. }
  512. if (DevExt->MappingTable) {
  513. ExFreePool(DevExt->MappingTable);
  514. DevExt->MappingTable = NULL;
  515. }
  516. DevExt->KeyboardReportIdValid = FALSE;
  517. DevExt->StandbyReportIdValid = FALSE;
  518. }
  519. NTSTATUS
  520. HidIrStopCompletion(
  521. IN PDEVICE_OBJECT DeviceObject,
  522. IN PIRP Irp
  523. )
  524. /*++
  525. Routine Description:
  526. Stops a given instance of a device. Work done here occurs after the parent
  527. has done its stop device.
  528. Arguments:
  529. DeviceObject - pointer to the device object.
  530. Return Value:
  531. NT status code
  532. --*/
  533. {
  534. PHIDIR_EXTENSION devExt;
  535. NTSTATUS ntStatus;
  536. PAGED_CODE();
  537. HidIrKdPrint((3, "HidIrStopCompletion Enter"));
  538. //
  539. // Get a pointer to the device extension
  540. //
  541. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  542. HidIrKdPrint((3, "DeviceExtension = %x", devExt));
  543. ntStatus = Irp->IoStatus.Status;
  544. if(NT_SUCCESS(ntStatus)) {
  545. HidIrKdPrint((3, "DeviceObject (%x) was stopped!", DeviceObject));
  546. } else {
  547. //
  548. // The PnP call failed!
  549. //
  550. HidIrKdPrint((3, "DeviceObject (%x) failed to stop!", DeviceObject));
  551. }
  552. HidIrFreeResources(devExt);
  553. devExt->DeviceState = DEVICE_STATE_STOPPED;
  554. HidIrKdPrint((3, "HidIrStopCompletion Exit = %x", ntStatus));
  555. return ntStatus;
  556. }
  557. NTSTATUS
  558. HidIrCleanupDevice(
  559. IN PDEVICE_OBJECT DeviceObject
  560. )
  561. {
  562. PHIDIR_EXTENSION devExt;
  563. ULONG oldDeviceState;
  564. PAGED_CODE();
  565. HidIrKdPrint((3, "HidIrCleanupDevice Enter"));
  566. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  567. oldDeviceState = devExt->DeviceState;
  568. devExt->DeviceState = DEVICE_STATE_REMOVING;
  569. if (devExt->QueryRemove) {
  570. // We are severing our relationship with this device
  571. // through a disable/uninstall in device manager.
  572. // If the device is virtually cabled, we must "unplug"
  573. // that device so that it can go elsewhere.
  574. }
  575. if (oldDeviceState == DEVICE_STATE_RUNNING) {
  576. HidIrDecrementPendingRequestCount(devExt);
  577. } else {
  578. ASSERT( devExt->NumPendingRequests == -1 );
  579. }
  580. return STATUS_SUCCESS;
  581. }
  582. NTSTATUS
  583. HidIrRemoveDevice(
  584. IN PDEVICE_OBJECT DeviceObject
  585. )
  586. /*++
  587. Routine Description:
  588. Removes a given instance of a device.
  589. Arguments:
  590. DeviceObject - pointer to the device object.
  591. Return Value:
  592. NT status code
  593. --*/
  594. {
  595. NTSTATUS ntStatus = STATUS_SUCCESS;
  596. PHIDIR_EXTENSION devExt;
  597. PAGED_CODE();
  598. HidIrKdPrint((3, "HidIrRemoveDevice Enter"));
  599. //
  600. // Get a pointer to the device extension
  601. //
  602. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  603. HidIrKdPrint((3, "DeviceExtension = %x", devExt));
  604. HidIrCleanupDevice(DeviceObject);
  605. KeWaitForSingleObject( &devExt->AllRequestsCompleteEvent,
  606. Executive,
  607. KernelMode,
  608. FALSE,
  609. NULL );
  610. KeCancelTimer( &devExt->IgnoreStandbyTimer );
  611. HidIrFreeResources(devExt);
  612. ASSERT(devExt->NumPendingRequests == -1);
  613. HidIrKdPrint((3, "HidIrRemoveDevice = %x", ntStatus));
  614. return ntStatus;
  615. }
  616. NTSTATUS
  617. HidIrPnP(
  618. IN PDEVICE_OBJECT DeviceObject,
  619. IN PIRP Irp
  620. )
  621. /*++
  622. Routine Description:
  623. Process the PnP IRPs sent to this device.
  624. Arguments:
  625. DeviceObject - pointer to a device object.
  626. Irp - pointer to an I/O Request Packet.
  627. Return Value:
  628. NT status code.
  629. --*/
  630. {
  631. NTSTATUS ntStatus = STATUS_SUCCESS;
  632. PIO_STACK_LOCATION IrpStack;
  633. PIO_STACK_LOCATION NextStack;
  634. PHIDIR_EXTENSION devExt;
  635. PAGED_CODE();
  636. //
  637. // Get a pointer to the device extension
  638. //
  639. devExt = GET_MINIDRIVER_HIDIR_EXTENSION(DeviceObject);
  640. //
  641. // Get a pointer to the current location in the Irp
  642. //
  643. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  644. HidIrKdPrint((3, "HidIrPnP fn %x DeviceObject = %x DeviceExtension = %x", IrpStack->MinorFunction, DeviceObject, devExt));
  645. switch(IrpStack->MinorFunction)
  646. {
  647. case IRP_MN_START_DEVICE:
  648. ntStatus = HidIrStartDevice(DeviceObject);
  649. break;
  650. case IRP_MN_STOP_DEVICE:
  651. ntStatus = HidIrStopDevice(DeviceObject);
  652. break;
  653. case IRP_MN_SURPRISE_REMOVAL:
  654. ntStatus = HidIrCleanupDevice(DeviceObject);
  655. break;
  656. case IRP_MN_QUERY_REMOVE_DEVICE:
  657. devExt->QueryRemove = TRUE;
  658. break;
  659. case IRP_MN_CANCEL_REMOVE_DEVICE:
  660. devExt->QueryRemove = FALSE;
  661. break;
  662. case IRP_MN_REMOVE_DEVICE:
  663. ntStatus = HidIrRemoveDevice(DeviceObject);
  664. break;
  665. }
  666. if (NT_SUCCESS(ntStatus)) {
  667. ntStatus = HidIrCallDriverSynchronous(DeviceObject, Irp);
  668. switch(IrpStack->MinorFunction)
  669. {
  670. case IRP_MN_START_DEVICE:
  671. if (NT_SUCCESS(ntStatus)) {
  672. ntStatus = HidIrStartCompletion(DeviceObject, Irp);
  673. Irp->IoStatus.Status = ntStatus;
  674. }
  675. if (!NT_SUCCESS(ntStatus)) {
  676. HidIrDecrementPendingRequestCount(devExt);
  677. }
  678. break;
  679. case IRP_MN_STOP_DEVICE:
  680. ntStatus = HidIrStopCompletion(DeviceObject, Irp);
  681. break;
  682. default:
  683. break;
  684. }
  685. }
  686. // Set the status of the Irp
  687. Irp->IoStatus.Status = ntStatus;
  688. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  689. HidIrKdPrint((3, "HidIrPnP Exit status %x", ntStatus));
  690. return ntStatus;
  691. }