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.

2756 lines
70 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. bulkpnp.c
  5. Abstract:
  6. Bulk USB device driver for Intel 82930 USB test board
  7. Plug and Play module.
  8. This file contains routines to handle pnp requests.
  9. These routines are not USB specific but is required
  10. for every driver which conforms to the WDM model.
  11. Environment:
  12. Kernel mode
  13. Notes:
  14. Copyright (c) 2000 Microsoft Corporation.
  15. All Rights Reserved.
  16. --*/
  17. #include "bulkusb.h"
  18. #include "bulkpnp.h"
  19. #include "bulkpwr.h"
  20. #include "bulkdev.h"
  21. #include "bulkrwr.h"
  22. #include "bulkwmi.h"
  23. #include "bulkusr.h"
  24. NTSTATUS
  25. BulkUsb_DispatchPnP(
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp
  28. )
  29. /*++
  30. Routine Description:
  31. The plug and play dispatch routines.
  32. Most of these requests the driver will completely ignore.
  33. In all cases it must pass on the IRP to the lower driver.
  34. Arguments:
  35. DeviceObject - pointer to a device object.
  36. Irp - pointer to an I/O Request Packet.
  37. Return Value:
  38. NT status value
  39. --*/
  40. {
  41. PIO_STACK_LOCATION irpStack;
  42. PDEVICE_EXTENSION deviceExtension;
  43. KEVENT startDeviceEvent;
  44. NTSTATUS ntStatus;
  45. //
  46. // initialize variables
  47. //
  48. irpStack = IoGetCurrentIrpStackLocation(Irp);
  49. deviceExtension = DeviceObject->DeviceExtension;
  50. //
  51. // since the device is removed, fail the Irp.
  52. //
  53. if(Removed == deviceExtension->DeviceState) {
  54. ntStatus = STATUS_DELETE_PENDING;
  55. Irp->IoStatus.Status = ntStatus;
  56. Irp->IoStatus.Information = 0;
  57. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  58. return ntStatus;
  59. }
  60. BulkUsb_DbgPrint(3, ("///////////////////////////////////////////\n"));
  61. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPnP::"));
  62. BulkUsb_IoIncrement(deviceExtension);
  63. if(irpStack->MinorFunction == IRP_MN_START_DEVICE) {
  64. ASSERT(deviceExtension->IdleReqPend == 0);
  65. }
  66. else {
  67. if(deviceExtension->SSEnable) {
  68. CancelSelectSuspend(deviceExtension);
  69. }
  70. }
  71. BulkUsb_DbgPrint(2, (PnPMinorFunctionString(irpStack->MinorFunction)));
  72. switch(irpStack->MinorFunction) {
  73. case IRP_MN_START_DEVICE:
  74. ntStatus = HandleStartDevice(DeviceObject, Irp);
  75. break;
  76. case IRP_MN_QUERY_STOP_DEVICE:
  77. //
  78. // if we cannot stop the device, we fail the query stop irp
  79. //
  80. ntStatus = CanStopDevice(DeviceObject, Irp);
  81. if(NT_SUCCESS(ntStatus)) {
  82. ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
  83. return ntStatus;
  84. }
  85. break;
  86. case IRP_MN_CANCEL_STOP_DEVICE:
  87. ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
  88. break;
  89. case IRP_MN_STOP_DEVICE:
  90. ntStatus = HandleStopDevice(DeviceObject, Irp);
  91. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPnP::IRP_MN_STOP_DEVICE::"));
  92. BulkUsb_IoDecrement(deviceExtension);
  93. return ntStatus;
  94. case IRP_MN_QUERY_REMOVE_DEVICE:
  95. //
  96. // if we cannot remove the device, we fail the query remove irp
  97. //
  98. ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
  99. return ntStatus;
  100. case IRP_MN_CANCEL_REMOVE_DEVICE:
  101. ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
  102. break;
  103. case IRP_MN_SURPRISE_REMOVAL:
  104. ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
  105. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
  106. BulkUsb_IoDecrement(deviceExtension);
  107. return ntStatus;
  108. case IRP_MN_REMOVE_DEVICE:
  109. ntStatus = HandleRemoveDevice(DeviceObject, Irp);
  110. return ntStatus;
  111. case IRP_MN_QUERY_CAPABILITIES:
  112. ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
  113. break;
  114. default:
  115. IoSkipCurrentIrpStackLocation(Irp);
  116. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  117. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPnP::default::"));
  118. BulkUsb_IoDecrement(deviceExtension);
  119. return ntStatus;
  120. } // switch
  121. //
  122. // complete request
  123. //
  124. Irp->IoStatus.Status = ntStatus;
  125. Irp->IoStatus.Information = 0;
  126. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  127. //
  128. // decrement count
  129. //
  130. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchPnP::"));
  131. BulkUsb_IoDecrement(deviceExtension);
  132. return ntStatus;
  133. }
  134. NTSTATUS
  135. HandleStartDevice(
  136. IN PDEVICE_OBJECT DeviceObject,
  137. IN PIRP Irp
  138. )
  139. /*++
  140. Routine Description:
  141. This is the dispatch routine for IRP_MN_START_DEVICE
  142. Arguments:
  143. DeviceObject - pointer to a device object.
  144. Irp - I/O request packet
  145. Return Value:
  146. NT status value
  147. --*/
  148. {
  149. KIRQL oldIrql;
  150. KEVENT startDeviceEvent;
  151. NTSTATUS ntStatus;
  152. PDEVICE_EXTENSION deviceExtension;
  153. LARGE_INTEGER dueTime;
  154. BulkUsb_DbgPrint(3, ("HandleStartDevice - begins\n"));
  155. //
  156. // initialize variables
  157. //
  158. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  159. deviceExtension->UsbConfigurationDescriptor = NULL;
  160. deviceExtension->UsbInterface = NULL;
  161. deviceExtension->PipeContext = NULL;
  162. //
  163. // We cannot touch the device (send it any non pnp irps) until a
  164. // start device has been passed down to the lower drivers.
  165. // first pass the Irp down
  166. //
  167. KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
  168. IoCopyCurrentIrpStackLocationToNext(Irp);
  169. IoSetCompletionRoutine(Irp,
  170. (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
  171. (PVOID)&startDeviceEvent,
  172. TRUE,
  173. TRUE,
  174. TRUE);
  175. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  176. if(ntStatus == STATUS_PENDING) {
  177. KeWaitForSingleObject(&startDeviceEvent,
  178. Executive,
  179. KernelMode,
  180. FALSE,
  181. NULL);
  182. ntStatus = Irp->IoStatus.Status;
  183. }
  184. if(!NT_SUCCESS(ntStatus)) {
  185. BulkUsb_DbgPrint(1, ("Lower drivers failed this Irp\n"));
  186. return ntStatus;
  187. }
  188. //
  189. // Read the device descriptor, configuration descriptor
  190. // and select the interface descriptors
  191. //
  192. ntStatus = ReadandSelectDescriptors(DeviceObject);
  193. if(!NT_SUCCESS(ntStatus)) {
  194. BulkUsb_DbgPrint(1, ("ReadandSelectDescriptors failed\n"));
  195. return ntStatus;
  196. }
  197. //
  198. // enable the symbolic links for system components to open
  199. // handles to the device
  200. //
  201. ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
  202. TRUE);
  203. if(!NT_SUCCESS(ntStatus)) {
  204. BulkUsb_DbgPrint(1, ("IoSetDeviceInterfaceState:enable:failed\n"));
  205. return ntStatus;
  206. }
  207. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  208. SET_NEW_PNP_STATE(deviceExtension, Working);
  209. deviceExtension->QueueState = AllowRequests;
  210. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  211. //
  212. // initialize wait wake outstanding flag to false.
  213. // and issue a wait wake.
  214. deviceExtension->FlagWWOutstanding = 0;
  215. deviceExtension->FlagWWCancel = 0;
  216. deviceExtension->WaitWakeIrp = NULL;
  217. if(deviceExtension->WaitWakeEnable) {
  218. IssueWaitWake(deviceExtension);
  219. }
  220. ProcessQueuedRequests(deviceExtension);
  221. if(WinXpOrBetter == deviceExtension->WdmVersion) {
  222. deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
  223. //
  224. // set timer.for selective suspend requests
  225. //
  226. if(deviceExtension->SSEnable) {
  227. dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms
  228. KeSetTimerEx(&deviceExtension->Timer,
  229. dueTime,
  230. IDLE_INTERVAL, // 5000 ms
  231. &deviceExtension->DeferredProcCall);
  232. deviceExtension->FreeIdleIrpCount = 0;
  233. }
  234. }
  235. BulkUsb_DbgPrint(3, ("HandleStartDevice - ends\n"));
  236. return ntStatus;
  237. }
  238. NTSTATUS
  239. ReadandSelectDescriptors(
  240. IN PDEVICE_OBJECT DeviceObject
  241. )
  242. /*++
  243. Routine Description:
  244. This routine configures the USB device.
  245. In this routines we get the device descriptor,
  246. the configuration descriptor and select the
  247. configuration descriptor.
  248. Arguments:
  249. DeviceObject - pointer to a device object
  250. Return Value:
  251. NTSTATUS - NT status value.
  252. --*/
  253. {
  254. PURB urb;
  255. ULONG siz;
  256. NTSTATUS ntStatus;
  257. PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
  258. //
  259. // initialize variables
  260. //
  261. urb = NULL;
  262. deviceDescriptor = NULL;
  263. //
  264. // 1. Read the device descriptor
  265. //
  266. urb = ExAllocatePool(NonPagedPool,
  267. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  268. if(urb) {
  269. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  270. deviceDescriptor = ExAllocatePool(NonPagedPool, siz);
  271. if(deviceDescriptor) {
  272. UsbBuildGetDescriptorRequest(
  273. urb,
  274. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  275. USB_DEVICE_DESCRIPTOR_TYPE,
  276. 0,
  277. 0,
  278. deviceDescriptor,
  279. NULL,
  280. siz,
  281. NULL);
  282. ntStatus = CallUSBD(DeviceObject, urb);
  283. if(NT_SUCCESS(ntStatus)) {
  284. ASSERT(deviceDescriptor->bNumConfigurations);
  285. ntStatus = ConfigureDevice(DeviceObject);
  286. }
  287. ExFreePool(urb);
  288. ExFreePool(deviceDescriptor);
  289. }
  290. else {
  291. BulkUsb_DbgPrint(1, ("Failed to allocate memory for deviceDescriptor\n"));
  292. ExFreePool(urb);
  293. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  294. }
  295. }
  296. else {
  297. BulkUsb_DbgPrint(1, ("Failed to allocate memory for urb\n"));
  298. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  299. }
  300. return ntStatus;
  301. }
  302. NTSTATUS
  303. ConfigureDevice(
  304. IN PDEVICE_OBJECT DeviceObject
  305. )
  306. /*++
  307. Routine Description:
  308. This helper routine reads the configuration descriptor
  309. for the device in couple of steps.
  310. Arguments:
  311. DeviceObject - pointer to a device object
  312. Return Value:
  313. NTSTATUS - NT status value
  314. --*/
  315. {
  316. PURB urb;
  317. ULONG siz;
  318. NTSTATUS ntStatus;
  319. PDEVICE_EXTENSION deviceExtension;
  320. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  321. //
  322. // initialize the variables
  323. //
  324. urb = NULL;
  325. configurationDescriptor = NULL;
  326. deviceExtension = DeviceObject->DeviceExtension;
  327. //
  328. // Read the first configuration descriptor
  329. // This requires two steps:
  330. // 1. Read the fixed sized configuration desciptor (CD)
  331. // 2. Read the CD with all embedded interface and endpoint descriptors
  332. //
  333. urb = ExAllocatePool(NonPagedPool,
  334. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  335. if(urb) {
  336. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  337. configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
  338. if(configurationDescriptor) {
  339. UsbBuildGetDescriptorRequest(
  340. urb,
  341. (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  342. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  343. 0,
  344. 0,
  345. configurationDescriptor,
  346. NULL,
  347. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  348. NULL);
  349. ntStatus = CallUSBD(DeviceObject, urb);
  350. if(!NT_SUCCESS(ntStatus)) {
  351. BulkUsb_DbgPrint(1, ("UsbBuildGetDescriptorRequest failed\n"));
  352. goto ConfigureDevice_Exit;
  353. }
  354. }
  355. else {
  356. BulkUsb_DbgPrint(1, ("Failed to allocate mem for config Descriptor\n"));
  357. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  358. goto ConfigureDevice_Exit;
  359. }
  360. siz = configurationDescriptor->wTotalLength;
  361. ExFreePool(configurationDescriptor);
  362. configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
  363. if(configurationDescriptor) {
  364. UsbBuildGetDescriptorRequest(
  365. urb,
  366. (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  367. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  368. 0,
  369. 0,
  370. configurationDescriptor,
  371. NULL,
  372. siz,
  373. NULL);
  374. ntStatus = CallUSBD(DeviceObject, urb);
  375. if(!NT_SUCCESS(ntStatus)) {
  376. BulkUsb_DbgPrint(1,("Failed to read configuration descriptor\n"));
  377. goto ConfigureDevice_Exit;
  378. }
  379. }
  380. else {
  381. BulkUsb_DbgPrint(1, ("Failed to alloc mem for config Descriptor\n"));
  382. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  383. goto ConfigureDevice_Exit;
  384. }
  385. }
  386. else {
  387. BulkUsb_DbgPrint(1, ("Failed to allocate memory for urb\n"));
  388. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  389. goto ConfigureDevice_Exit;
  390. }
  391. if(configurationDescriptor) {
  392. //
  393. // save a copy of configurationDescriptor in deviceExtension
  394. // remember to free it later.
  395. //
  396. deviceExtension->UsbConfigurationDescriptor = configurationDescriptor;
  397. if(configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
  398. {
  399. //
  400. // this configuration supports remote wakeup
  401. //
  402. deviceExtension->WaitWakeEnable = 1;
  403. }
  404. else
  405. {
  406. deviceExtension->WaitWakeEnable = 0;
  407. }
  408. ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
  409. }
  410. else {
  411. deviceExtension->UsbConfigurationDescriptor = NULL;
  412. }
  413. ConfigureDevice_Exit:
  414. if(urb) {
  415. ExFreePool(urb);
  416. }
  417. return ntStatus;
  418. }
  419. NTSTATUS
  420. SelectInterfaces(
  421. IN PDEVICE_OBJECT DeviceObject,
  422. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
  423. )
  424. /*++
  425. Routine Description:
  426. This helper routine selects the configuration
  427. Arguments:
  428. DeviceObject - pointer to device object
  429. ConfigurationDescriptor - pointer to the configuration
  430. descriptor for the device
  431. Return Value:
  432. NT status value
  433. --*/
  434. {
  435. LONG numberOfInterfaces,
  436. interfaceNumber,
  437. interfaceindex;
  438. ULONG i;
  439. PURB urb;
  440. PUCHAR pInf;
  441. NTSTATUS ntStatus;
  442. PDEVICE_EXTENSION deviceExtension;
  443. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  444. PUSBD_INTERFACE_LIST_ENTRY interfaceList,
  445. tmp;
  446. PUSBD_INTERFACE_INFORMATION Interface;
  447. //
  448. // initialize the variables
  449. //
  450. urb = NULL;
  451. Interface = NULL;
  452. interfaceDescriptor = NULL;
  453. deviceExtension = DeviceObject->DeviceExtension;
  454. numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  455. interfaceindex = interfaceNumber = 0;
  456. //
  457. // Parse the configuration descriptor for the interface;
  458. //
  459. tmp = interfaceList =
  460. ExAllocatePool(
  461. NonPagedPool,
  462. sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
  463. if(!tmp) {
  464. BulkUsb_DbgPrint(1, ("Failed to allocate mem for interfaceList\n"));
  465. return STATUS_INSUFFICIENT_RESOURCES;
  466. }
  467. while(interfaceNumber < numberOfInterfaces) {
  468. interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
  469. ConfigurationDescriptor,
  470. ConfigurationDescriptor,
  471. interfaceindex,
  472. 0, -1, -1, -1);
  473. if(interfaceDescriptor) {
  474. interfaceList->InterfaceDescriptor = interfaceDescriptor;
  475. interfaceList->Interface = NULL;
  476. interfaceList++;
  477. interfaceNumber++;
  478. }
  479. interfaceindex++;
  480. }
  481. interfaceList->InterfaceDescriptor = NULL;
  482. interfaceList->Interface = NULL;
  483. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
  484. if(urb) {
  485. Interface = &urb->UrbSelectConfiguration.Interface;
  486. for(i=0; i<Interface->NumberOfPipes; i++) {
  487. //
  488. // perform pipe initialization here
  489. // set the transfer size and any pipe flags we use
  490. // USBD sets the rest of the Interface struct members
  491. //
  492. Interface->Pipes[i].MaximumTransferSize =
  493. USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
  494. }
  495. ntStatus = CallUSBD(DeviceObject, urb);
  496. if(NT_SUCCESS(ntStatus)) {
  497. //
  498. // save a copy of interface information in the device extension.
  499. //
  500. deviceExtension->UsbInterface = ExAllocatePool(NonPagedPool,
  501. Interface->Length);
  502. if(deviceExtension->UsbInterface) {
  503. RtlCopyMemory(deviceExtension->UsbInterface,
  504. Interface,
  505. Interface->Length);
  506. }
  507. else {
  508. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  509. BulkUsb_DbgPrint(1, ("memory alloc for UsbInterface failed\n"));
  510. }
  511. //
  512. // Dump the interface to the debugger
  513. //
  514. Interface = &urb->UrbSelectConfiguration.Interface;
  515. BulkUsb_DbgPrint(3, ("---------\n"));
  516. BulkUsb_DbgPrint(3, ("NumberOfPipes 0x%x\n",
  517. Interface->NumberOfPipes));
  518. BulkUsb_DbgPrint(3, ("Length 0x%x\n",
  519. Interface->Length));
  520. BulkUsb_DbgPrint(3, ("Alt Setting 0x%x\n",
  521. Interface->AlternateSetting));
  522. BulkUsb_DbgPrint(3, ("Interface Number 0x%x\n",
  523. Interface->InterfaceNumber));
  524. BulkUsb_DbgPrint(3, ("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
  525. Interface->Class,
  526. Interface->SubClass,
  527. Interface->Protocol));
  528. //
  529. // Initialize the PipeContext
  530. // Dump the pipe info
  531. //
  532. if(Interface->NumberOfPipes) {
  533. deviceExtension->PipeContext =
  534. ExAllocatePool(NonPagedPool,
  535. Interface->NumberOfPipes *
  536. sizeof(BULKUSB_PIPE_CONTEXT));
  537. if(deviceExtension->PipeContext) {
  538. for(i=0; i<Interface->NumberOfPipes; i++) {
  539. deviceExtension->PipeContext[i].PipeOpen = FALSE;
  540. }
  541. }
  542. else {
  543. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  544. BulkUsb_DbgPrint(1, ("memory alloc for UsbInterface failed\n"));
  545. }
  546. }
  547. for(i=0; i<Interface->NumberOfPipes; i++) {
  548. BulkUsb_DbgPrint(3, ("---------\n"));
  549. BulkUsb_DbgPrint(3, ("PipeType 0x%x\n",
  550. Interface->Pipes[i].PipeType));
  551. BulkUsb_DbgPrint(3, ("EndpointAddress 0x%x\n",
  552. Interface->Pipes[i].EndpointAddress));
  553. BulkUsb_DbgPrint(3, ("MaxPacketSize 0x%x\n",
  554. Interface->Pipes[i].MaximumPacketSize));
  555. BulkUsb_DbgPrint(3, ("Interval 0x%x\n",
  556. Interface->Pipes[i].Interval));
  557. BulkUsb_DbgPrint(3, ("Handle 0x%x\n",
  558. Interface->Pipes[i].PipeHandle));
  559. BulkUsb_DbgPrint(3, ("MaximumTransferSize 0x%x\n",
  560. Interface->Pipes[i].MaximumTransferSize));
  561. }
  562. BulkUsb_DbgPrint(3, ("---------\n"));
  563. }
  564. else {
  565. BulkUsb_DbgPrint(1, ("Failed to select an interface\n"));
  566. }
  567. }
  568. else {
  569. BulkUsb_DbgPrint(1, ("USBD_CreateConfigurationRequestEx failed\n"));
  570. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  571. }
  572. if(tmp) {
  573. ExFreePool(tmp);
  574. }
  575. if(urb) {
  576. ExFreePool(urb);
  577. }
  578. return ntStatus;
  579. }
  580. NTSTATUS
  581. DeconfigureDevice(
  582. IN PDEVICE_OBJECT DeviceObject
  583. )
  584. /*++
  585. Routine Description:
  586. This routine is invoked when the device is removed or stopped.
  587. This routine de-configures the usb device.
  588. Arguments:
  589. DeviceObject - pointer to device object
  590. Return Value:
  591. NT status value
  592. --*/
  593. {
  594. PURB urb;
  595. ULONG siz;
  596. NTSTATUS ntStatus;
  597. //
  598. // initialize variables
  599. //
  600. siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  601. urb = ExAllocatePool(NonPagedPool, siz);
  602. if(urb) {
  603. UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
  604. ntStatus = CallUSBD(DeviceObject, urb);
  605. if(!NT_SUCCESS(ntStatus)) {
  606. BulkUsb_DbgPrint(3, ("Failed to deconfigure device\n"));
  607. }
  608. ExFreePool(urb);
  609. }
  610. else {
  611. BulkUsb_DbgPrint(1, ("Failed to allocate urb\n"));
  612. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  613. }
  614. return ntStatus;
  615. }
  616. NTSTATUS
  617. CallUSBD(
  618. IN PDEVICE_OBJECT DeviceObject,
  619. IN PURB Urb
  620. )
  621. /*++
  622. Routine Description:
  623. This routine synchronously submits an urb down the stack.
  624. Arguments:
  625. DeviceObject - pointer to device object
  626. Urb - USB request block
  627. Return Value:
  628. --*/
  629. {
  630. PIRP irp;
  631. KEVENT event;
  632. NTSTATUS ntStatus;
  633. IO_STATUS_BLOCK ioStatus;
  634. PIO_STACK_LOCATION nextStack;
  635. PDEVICE_EXTENSION deviceExtension;
  636. //
  637. // initialize the variables
  638. //
  639. irp = NULL;
  640. deviceExtension = DeviceObject->DeviceExtension;
  641. KeInitializeEvent(&event, NotificationEvent, FALSE);
  642. irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
  643. deviceExtension->TopOfStackDeviceObject,
  644. NULL,
  645. 0,
  646. NULL,
  647. 0,
  648. TRUE,
  649. &event,
  650. &ioStatus);
  651. if(!irp) {
  652. BulkUsb_DbgPrint(1, ("IoBuildDeviceIoControlRequest failed\n"));
  653. return STATUS_INSUFFICIENT_RESOURCES;
  654. }
  655. nextStack = IoGetNextIrpStackLocation(irp);
  656. ASSERT(nextStack != NULL);
  657. nextStack->Parameters.Others.Argument1 = Urb;
  658. BulkUsb_DbgPrint(3, ("CallUSBD::"));
  659. BulkUsb_IoIncrement(deviceExtension);
  660. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
  661. if(ntStatus == STATUS_PENDING) {
  662. KeWaitForSingleObject(&event,
  663. Executive,
  664. KernelMode,
  665. FALSE,
  666. NULL);
  667. ntStatus = ioStatus.Status;
  668. }
  669. BulkUsb_DbgPrint(3, ("CallUSBD::"));
  670. BulkUsb_IoDecrement(deviceExtension);
  671. return ntStatus;
  672. }
  673. NTSTATUS
  674. HandleQueryStopDevice(
  675. IN PDEVICE_OBJECT DeviceObject,
  676. IN PIRP Irp
  677. )
  678. /*++
  679. Routine Description:
  680. This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
  681. Arguments:
  682. DeviceObject - pointer to device object
  683. Irp - I/O request packet sent by the pnp manager.
  684. Return Value:
  685. NT status value
  686. --*/
  687. {
  688. KIRQL oldIrql;
  689. NTSTATUS ntStatus;
  690. PDEVICE_EXTENSION deviceExtension;
  691. BulkUsb_DbgPrint(3, ("HandleQueryStopDevice - begins\n"));
  692. //
  693. // initialize variables
  694. //
  695. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  696. //
  697. // If we can stop the device, we need to set the QueueState to
  698. // HoldRequests so further requests will be queued.
  699. //
  700. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  701. SET_NEW_PNP_STATE(deviceExtension, PendingStop);
  702. deviceExtension->QueueState = HoldRequests;
  703. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  704. //
  705. // wait for the existing ones to be finished.
  706. // first, decrement this operation
  707. //
  708. BulkUsb_DbgPrint(3, ("HandleQueryStopDevice::"));
  709. BulkUsb_IoDecrement(deviceExtension);
  710. KeWaitForSingleObject(&deviceExtension->StopEvent,
  711. Executive,
  712. KernelMode,
  713. FALSE,
  714. NULL);
  715. Irp->IoStatus.Status = STATUS_SUCCESS;
  716. Irp->IoStatus.Information = 0;
  717. IoSkipCurrentIrpStackLocation(Irp);
  718. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  719. BulkUsb_DbgPrint(3, ("HandleQueryStopDevice - ends\n"));
  720. return ntStatus;
  721. }
  722. NTSTATUS
  723. HandleCancelStopDevice(
  724. IN PDEVICE_OBJECT DeviceObject,
  725. IN PIRP Irp
  726. )
  727. /*++
  728. Routine Description:
  729. This routine services Irp of minor type IRP_MN_CANCEL_STOP_DEVICE
  730. Arguments:
  731. DeviceObject - pointer to device object
  732. Irp - I/O request packet sent by the pnp manager.
  733. Return Value:
  734. NT value
  735. --*/
  736. {
  737. KIRQL oldIrql;
  738. KEVENT event;
  739. NTSTATUS ntStatus;
  740. PDEVICE_EXTENSION deviceExtension;
  741. BulkUsb_DbgPrint(3, ("HandleCancelStopDevice - begins\n"));
  742. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  743. //
  744. // Send this IRP down and wait for it to come back.
  745. // Set the QueueState flag to AllowRequests,
  746. // and process all the previously queued up IRPs.
  747. //
  748. // First check to see whether you have received cancel-stop
  749. // without first receiving a query-stop. This could happen if someone
  750. // above us fails a query-stop and passes down the subsequent
  751. // cancel-stop.
  752. //
  753. if(PendingStop == deviceExtension->DeviceState) {
  754. KeInitializeEvent(&event, NotificationEvent, FALSE);
  755. IoCopyCurrentIrpStackLocationToNext(Irp);
  756. IoSetCompletionRoutine(Irp,
  757. (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
  758. (PVOID)&event,
  759. TRUE,
  760. TRUE,
  761. TRUE);
  762. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  763. if(ntStatus == STATUS_PENDING) {
  764. KeWaitForSingleObject(&event,
  765. Executive,
  766. KernelMode,
  767. FALSE,
  768. NULL);
  769. ntStatus = Irp->IoStatus.Status;
  770. }
  771. if(NT_SUCCESS(ntStatus)) {
  772. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  773. RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
  774. deviceExtension->QueueState = AllowRequests;
  775. ASSERT(deviceExtension->DeviceState == Working);
  776. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  777. ProcessQueuedRequests(deviceExtension);
  778. }
  779. }
  780. else {
  781. // spurious Irp
  782. ntStatus = STATUS_SUCCESS;
  783. }
  784. BulkUsb_DbgPrint(3, ("HandleCancelStopDevice - ends\n"));
  785. return ntStatus;
  786. }
  787. NTSTATUS
  788. HandleStopDevice(
  789. IN PDEVICE_OBJECT DeviceObject,
  790. IN PIRP Irp
  791. )
  792. /*++
  793. Routine Description:
  794. This routine services Irp of minor type IRP_MN_STOP_DEVICE
  795. Arguments:
  796. DeviceObject - pointer to device object
  797. Irp - I/O request packet sent by the pnp manager.
  798. Return Value:
  799. NT status value
  800. --*/
  801. {
  802. KIRQL oldIrql;
  803. NTSTATUS ntStatus;
  804. PDEVICE_EXTENSION deviceExtension;
  805. BulkUsb_DbgPrint(3, ("HandleStopDevice - begins\n"));
  806. //
  807. // initialize variables
  808. //
  809. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  810. if(WinXpOrBetter == deviceExtension->WdmVersion) {
  811. if(deviceExtension->SSEnable) {
  812. //
  813. // Cancel the timer so that the DPCs are no longer fired.
  814. // Thus, we are making judicious usage of our resources.
  815. // we do not need DPCs because the device is stopping.
  816. // The timers are re-initialized while handling the start
  817. // device irp.
  818. //
  819. KeCancelTimer(&deviceExtension->Timer);
  820. //
  821. // after the device is stopped, it can be surprise removed.
  822. // we set this to 0, so that we do not attempt to cancel
  823. // the timer while handling surprise remove or remove irps.
  824. // when we get the start device request, this flag will be
  825. // reinitialized.
  826. //
  827. deviceExtension->SSEnable = 0;
  828. //
  829. // make sure that if a DPC was fired before we called cancel timer,
  830. // then the DPC and work-time have run to their completion
  831. //
  832. KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
  833. Executive,
  834. KernelMode,
  835. FALSE,
  836. NULL);
  837. //
  838. // make sure that the selective suspend request has been completed.
  839. //
  840. KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
  841. Executive,
  842. KernelMode,
  843. FALSE,
  844. NULL);
  845. }
  846. }
  847. //
  848. // after the stop Irp is sent to the lower driver object,
  849. // the driver must not send any more Irps down that touch
  850. // the device until another Start has occurred.
  851. //
  852. if(deviceExtension->WaitWakeEnable) {
  853. CancelWaitWake(deviceExtension);
  854. }
  855. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  856. SET_NEW_PNP_STATE(deviceExtension, Stopped);
  857. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  858. //
  859. // This is the right place to actually give up all the resources used
  860. // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
  861. // etc.
  862. //
  863. ReleaseMemory(DeviceObject);
  864. ntStatus = DeconfigureDevice(DeviceObject);
  865. Irp->IoStatus.Status = ntStatus;
  866. Irp->IoStatus.Information = 0;
  867. IoSkipCurrentIrpStackLocation(Irp);
  868. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  869. BulkUsb_DbgPrint(3, ("HandleStopDevice - ends\n"));
  870. return ntStatus;
  871. }
  872. NTSTATUS
  873. HandleQueryRemoveDevice(
  874. IN PDEVICE_OBJECT DeviceObject,
  875. IN PIRP Irp
  876. )
  877. /*++
  878. Routine Description:
  879. This routine services Irp of minor type IRP_MN_QUERY_REMOVE_DEVICE
  880. Arguments:
  881. DeviceObject - pointer to device object
  882. Irp - I/O request packet sent by the pnp manager.
  883. Return Value:
  884. NT status value
  885. --*/
  886. {
  887. KIRQL oldIrql;
  888. NTSTATUS ntStatus;
  889. PDEVICE_EXTENSION deviceExtension;
  890. BulkUsb_DbgPrint(3, ("HandleQueryRemoveDevice - begins\n"));
  891. //
  892. // initialize variables
  893. //
  894. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  895. //
  896. // If we can allow removal of the device, we should set the QueueState
  897. // to HoldRequests so further requests will be queued. This is required
  898. // so that we can process queued up requests in cancel-remove just in
  899. // case somebody else in the stack fails the query-remove.
  900. //
  901. ntStatus = CanRemoveDevice(DeviceObject, Irp);
  902. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  903. deviceExtension->QueueState = HoldRequests;
  904. SET_NEW_PNP_STATE(deviceExtension, PendingRemove);
  905. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  906. BulkUsb_DbgPrint(3, ("HandleQueryRemoveDevice::"));
  907. BulkUsb_IoDecrement(deviceExtension);
  908. //
  909. // wait for all the requests to be completed
  910. //
  911. KeWaitForSingleObject(&deviceExtension->StopEvent,
  912. Executive,
  913. KernelMode,
  914. FALSE,
  915. NULL);
  916. Irp->IoStatus.Status = STATUS_SUCCESS;
  917. Irp->IoStatus.Information = 0;
  918. IoSkipCurrentIrpStackLocation(Irp);
  919. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  920. BulkUsb_DbgPrint(3, ("HandleQueryRemoveDevice - ends\n"));
  921. return ntStatus;
  922. }
  923. NTSTATUS
  924. HandleCancelRemoveDevice(
  925. IN PDEVICE_OBJECT DeviceObject,
  926. IN PIRP Irp
  927. )
  928. /*++
  929. Routine Description:
  930. This routine services Irp of minor type IRP_MN_CANCEL_REMOVE_DEVICE
  931. Arguments:
  932. DeviceObject - pointer to device object
  933. Irp - I/O request packet sent by the pnp manager.
  934. Return Value:
  935. NT status value
  936. --*/
  937. {
  938. KIRQL oldIrql;
  939. KEVENT event;
  940. NTSTATUS ntStatus;
  941. PDEVICE_EXTENSION deviceExtension;
  942. BulkUsb_DbgPrint(3, ("HandleCancelRemoveDevice - begins\n"));
  943. //
  944. // initialize variables
  945. //
  946. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  947. //
  948. // We need to reset the QueueState flag to ProcessRequest,
  949. // since the device resume its normal activities.
  950. //
  951. //
  952. // First check to see whether you have received cancel-remove
  953. // without first receiving a query-remove. This could happen if
  954. // someone above us fails a query-remove and passes down the
  955. // subsequent cancel-remove.
  956. //
  957. if(PendingRemove == deviceExtension->DeviceState) {
  958. KeInitializeEvent(&event, NotificationEvent, FALSE);
  959. IoCopyCurrentIrpStackLocationToNext(Irp);
  960. IoSetCompletionRoutine(Irp,
  961. (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
  962. (PVOID)&event,
  963. TRUE,
  964. TRUE,
  965. TRUE);
  966. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  967. if(ntStatus == STATUS_PENDING) {
  968. KeWaitForSingleObject(&event,
  969. Executive,
  970. KernelMode,
  971. FALSE,
  972. NULL);
  973. ntStatus = Irp->IoStatus.Status;
  974. }
  975. if(NT_SUCCESS(ntStatus)) {
  976. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  977. deviceExtension->QueueState = AllowRequests;
  978. RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
  979. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  980. //
  981. // process the queued requests that arrive between
  982. // QUERY_REMOVE and CANCEL_REMOVE
  983. //
  984. ProcessQueuedRequests(deviceExtension);
  985. }
  986. }
  987. else {
  988. //
  989. // spurious cancel-remove
  990. //
  991. ntStatus = STATUS_SUCCESS;
  992. }
  993. BulkUsb_DbgPrint(3, ("HandleCancelRemoveDevice - ends\n"));
  994. return ntStatus;
  995. }
  996. NTSTATUS
  997. HandleSurpriseRemoval(
  998. IN PDEVICE_OBJECT DeviceObject,
  999. IN PIRP Irp
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine services Irp of minor type IRP_MN_SURPRISE_REMOVAL
  1004. Arguments:
  1005. DeviceObject - pointer to device object
  1006. Irp - I/O request packet sent by the pnp manager.
  1007. Return Value:
  1008. NT status value
  1009. --*/
  1010. {
  1011. KIRQL oldIrql;
  1012. NTSTATUS ntStatus;
  1013. PDEVICE_EXTENSION deviceExtension;
  1014. BulkUsb_DbgPrint(3, ("HandleSurpriseRemoval - begins\n"));
  1015. //
  1016. // initialize variables
  1017. //
  1018. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1019. //
  1020. // 1. fail pending requests
  1021. // 2. return device and memory resources
  1022. // 3. disable interfaces
  1023. //
  1024. if(deviceExtension->WaitWakeEnable) {
  1025. CancelWaitWake(deviceExtension);
  1026. }
  1027. if(WinXpOrBetter == deviceExtension->WdmVersion) {
  1028. if(deviceExtension->SSEnable) {
  1029. //
  1030. // Cancel the timer so that the DPCs are no longer fired.
  1031. // we do not need DPCs because the device has been surprise
  1032. // removed
  1033. //
  1034. KeCancelTimer(&deviceExtension->Timer);
  1035. deviceExtension->SSEnable = 0;
  1036. //
  1037. // make sure that if a DPC was fired before we called cancel timer,
  1038. // then the DPC and work-time have run to their completion
  1039. //
  1040. KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
  1041. Executive,
  1042. KernelMode,
  1043. FALSE,
  1044. NULL);
  1045. //
  1046. // make sure that the selective suspend request has been completed.
  1047. //
  1048. KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
  1049. Executive,
  1050. KernelMode,
  1051. FALSE,
  1052. NULL);
  1053. }
  1054. }
  1055. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  1056. deviceExtension->QueueState = FailRequests;
  1057. SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved);
  1058. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  1059. ProcessQueuedRequests(deviceExtension);
  1060. ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
  1061. FALSE);
  1062. if(!NT_SUCCESS(ntStatus)) {
  1063. BulkUsb_DbgPrint(1, ("IoSetDeviceInterfaceState::disable:failed\n"));
  1064. }
  1065. RtlFreeUnicodeString(&deviceExtension->InterfaceName);
  1066. BulkUsb_AbortPipes(DeviceObject);
  1067. Irp->IoStatus.Status = STATUS_SUCCESS;
  1068. Irp->IoStatus.Information = 0;
  1069. IoSkipCurrentIrpStackLocation(Irp);
  1070. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  1071. BulkUsb_DbgPrint(3, ("HandleSurpriseRemoval - ends\n"));
  1072. return ntStatus;
  1073. }
  1074. NTSTATUS
  1075. HandleRemoveDevice(
  1076. IN PDEVICE_OBJECT DeviceObject,
  1077. IN PIRP Irp
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. This routine services Irp of minor type IRP_MN_REMOVE_DEVICE
  1082. Arguments:
  1083. DeviceObject - pointer to device object
  1084. Irp - I/O request packet sent by the pnp manager.
  1085. Return Value:
  1086. NT status value
  1087. --*/
  1088. {
  1089. KIRQL oldIrql;
  1090. KEVENT event;
  1091. ULONG requestCount;
  1092. NTSTATUS ntStatus;
  1093. PDEVICE_EXTENSION deviceExtension;
  1094. BulkUsb_DbgPrint(3, ("HandleRemoveDevice - begins\n"));
  1095. //
  1096. // initialize variables
  1097. //
  1098. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1099. //
  1100. // The Plug & Play system has dictated the removal of this device. We
  1101. // have no choice but to detach and delete the device object.
  1102. // (If we wanted to express an interest in preventing this removal,
  1103. // we should have failed the query remove IRP).
  1104. //
  1105. if(SurpriseRemoved != deviceExtension->DeviceState) {
  1106. //
  1107. // we are here after QUERY_REMOVE
  1108. //
  1109. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  1110. deviceExtension->QueueState = FailRequests;
  1111. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  1112. if(deviceExtension->WaitWakeEnable) {
  1113. CancelWaitWake(deviceExtension);
  1114. }
  1115. if(WinXpOrBetter == deviceExtension->WdmVersion) {
  1116. if(deviceExtension->SSEnable) {
  1117. //
  1118. // Cancel the timer so that the DPCs are no longer fired.
  1119. // we do not need DPCs because the device has been removed
  1120. //
  1121. KeCancelTimer(&deviceExtension->Timer);
  1122. deviceExtension->SSEnable = 0;
  1123. //
  1124. // make sure that if a DPC was fired before we called cancel timer,
  1125. // then the DPC and work-time have run to their completion
  1126. //
  1127. KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent,
  1128. Executive,
  1129. KernelMode,
  1130. FALSE,
  1131. NULL);
  1132. //
  1133. // make sure that the selective suspend request has been completed.
  1134. //
  1135. KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
  1136. Executive,
  1137. KernelMode,
  1138. FALSE,
  1139. NULL);
  1140. }
  1141. }
  1142. ProcessQueuedRequests(deviceExtension);
  1143. ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName,
  1144. FALSE);
  1145. if(!NT_SUCCESS(ntStatus)) {
  1146. BulkUsb_DbgPrint(1, ("IoSetDeviceInterfaceState::disable:failed\n"));
  1147. }
  1148. RtlFreeUnicodeString(&deviceExtension->InterfaceName);
  1149. BulkUsb_AbortPipes(DeviceObject);
  1150. }
  1151. KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  1152. SET_NEW_PNP_STATE(deviceExtension, Removed);
  1153. KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  1154. BulkUsb_WmiDeRegistration(deviceExtension);
  1155. //
  1156. // need 2 decrements
  1157. //
  1158. BulkUsb_DbgPrint(3, ("HandleRemoveDevice::"));
  1159. requestCount = BulkUsb_IoDecrement(deviceExtension);
  1160. ASSERT(requestCount > 0);
  1161. BulkUsb_DbgPrint(3, ("HandleRemoveDevice::"));
  1162. requestCount = BulkUsb_IoDecrement(deviceExtension);
  1163. KeWaitForSingleObject(&deviceExtension->RemoveEvent,
  1164. Executive,
  1165. KernelMode,
  1166. FALSE,
  1167. NULL);
  1168. ReleaseMemory(DeviceObject);
  1169. //
  1170. // We need to send the remove down the stack before we detach,
  1171. // but we don't need to wait for the completion of this operation
  1172. // (and to register a completion routine).
  1173. //
  1174. Irp->IoStatus.Status = STATUS_SUCCESS;
  1175. Irp->IoStatus.Information = 0;
  1176. IoSkipCurrentIrpStackLocation(Irp);
  1177. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  1178. //
  1179. // Detach the FDO from the device stack
  1180. //
  1181. IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
  1182. IoDeleteDevice(DeviceObject);
  1183. BulkUsb_DbgPrint(3, ("HandleRemoveDevice - ends\n"));
  1184. return ntStatus;
  1185. }
  1186. NTSTATUS
  1187. HandleQueryCapabilities(
  1188. IN PDEVICE_OBJECT DeviceObject,
  1189. IN PIRP Irp
  1190. )
  1191. /*++
  1192. Routine Description:
  1193. This routine services Irp of minor type IRP_MN_QUERY_CAPABILITIES
  1194. Arguments:
  1195. DeviceObject - pointer to device object
  1196. Irp - I/O request packet sent by the pnp manager.
  1197. Return Value:
  1198. NT status value
  1199. --*/
  1200. {
  1201. ULONG i;
  1202. KEVENT event;
  1203. NTSTATUS ntStatus;
  1204. PDEVICE_EXTENSION deviceExtension;
  1205. PDEVICE_CAPABILITIES pdc;
  1206. PIO_STACK_LOCATION irpStack;
  1207. BulkUsb_DbgPrint(3, ("HandleQueryCapabilities - begins\n"));
  1208. //
  1209. // initialize variables
  1210. //
  1211. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1212. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1213. pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
  1214. //
  1215. // We will provide here an example of an IRP that is processed
  1216. // both on its way down and on its way up: there might be no need for
  1217. // a function driver process this Irp (the bus driver will do that).
  1218. // The driver will wait for the lower drivers (the bus driver among
  1219. // them) to process this IRP, then it processes it again.
  1220. //
  1221. if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES)) {
  1222. BulkUsb_DbgPrint(1, ("HandleQueryCapabilities::request failed\n"));
  1223. ntStatus = STATUS_UNSUCCESSFUL;
  1224. return ntStatus;
  1225. }
  1226. //
  1227. // Add in the SurpriseRemovalOK bit before passing it down.
  1228. //
  1229. pdc->SurpriseRemovalOK = TRUE;
  1230. Irp->IoStatus.Status = STATUS_SUCCESS;
  1231. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1232. IoCopyCurrentIrpStackLocationToNext(Irp);
  1233. IoSetCompletionRoutine(Irp,
  1234. (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
  1235. (PVOID)&event,
  1236. TRUE,
  1237. TRUE,
  1238. TRUE);
  1239. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  1240. if(ntStatus == STATUS_PENDING) {
  1241. KeWaitForSingleObject(&event,
  1242. Executive,
  1243. KernelMode,
  1244. FALSE,
  1245. NULL);
  1246. ntStatus = Irp->IoStatus.Status;
  1247. }
  1248. //
  1249. // initialize PowerDownLevel to disabled
  1250. //
  1251. deviceExtension->PowerDownLevel = PowerDeviceUnspecified;
  1252. if(NT_SUCCESS(ntStatus)) {
  1253. deviceExtension->DeviceCapabilities = *pdc;
  1254. for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++) {
  1255. if(deviceExtension->DeviceCapabilities.DeviceState[i] <
  1256. PowerDeviceD3) {
  1257. deviceExtension->PowerDownLevel =
  1258. deviceExtension->DeviceCapabilities.DeviceState[i];
  1259. }
  1260. }
  1261. //
  1262. // since its safe to surprise-remove this device, we shall
  1263. // set the SurpriseRemoveOK flag to supress any dialog to
  1264. // user.
  1265. //
  1266. pdc->SurpriseRemovalOK = 1;
  1267. }
  1268. if(deviceExtension->PowerDownLevel == PowerDeviceUnspecified ||
  1269. deviceExtension->PowerDownLevel <= PowerDeviceD0) {
  1270. deviceExtension->PowerDownLevel = PowerDeviceD2;
  1271. }
  1272. BulkUsb_DbgPrint(3, ("HandleQueryCapabilities - ends\n"));
  1273. return ntStatus;
  1274. }
  1275. VOID
  1276. DpcRoutine(
  1277. IN PKDPC Dpc,
  1278. IN PVOID DeferredContext,
  1279. IN PVOID SystemArgument1,
  1280. IN PVOID SystemArgument2
  1281. )
  1282. /*++
  1283. Routine Description:
  1284. DPC routine triggered by the timer to check the idle state
  1285. of the device and submit an idle request for the device.
  1286. Arguments:
  1287. DeferredContext - context for the dpc routine.
  1288. DeviceObject in our case.
  1289. Return Value:
  1290. None
  1291. --*/
  1292. {
  1293. NTSTATUS ntStatus;
  1294. PDEVICE_OBJECT deviceObject;
  1295. PDEVICE_EXTENSION deviceExtension;
  1296. PIO_WORKITEM item;
  1297. BulkUsb_DbgPrint(3, ("DpcRoutine - begins\n"));
  1298. deviceObject = (PDEVICE_OBJECT)DeferredContext;
  1299. deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
  1300. //
  1301. // Clear this event since a DPC has been fired!
  1302. //
  1303. KeClearEvent(&deviceExtension->NoDpcWorkItemPendingEvent);
  1304. if(CanDeviceSuspend(deviceExtension)) {
  1305. BulkUsb_DbgPrint(3, ("Device is Idle\n"));
  1306. item = IoAllocateWorkItem(deviceObject);
  1307. if(item) {
  1308. IoQueueWorkItem(item,
  1309. IdleRequestWorkerRoutine,
  1310. DelayedWorkQueue,
  1311. item);
  1312. ntStatus = STATUS_PENDING;
  1313. }
  1314. else {
  1315. BulkUsb_DbgPrint(3, ("Cannot alloc memory for work item\n"));
  1316. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1317. //
  1318. // signal the NoDpcWorkItemPendingEvent.
  1319. //
  1320. KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent,
  1321. IO_NO_INCREMENT,
  1322. FALSE);
  1323. }
  1324. }
  1325. else {
  1326. BulkUsb_DbgPrint(3, ("Idle event not signaled\n"));
  1327. //
  1328. // signal the NoDpcWorkItemPendingEvent.
  1329. //
  1330. KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent,
  1331. IO_NO_INCREMENT,
  1332. FALSE);
  1333. }
  1334. BulkUsb_DbgPrint(3, ("DpcRoutine - ends\n"));
  1335. }
  1336. VOID
  1337. IdleRequestWorkerRoutine(
  1338. IN PDEVICE_OBJECT DeviceObject,
  1339. IN PVOID Context
  1340. )
  1341. /*++
  1342. Routine Description:
  1343. This is the work item fired from the DPC.
  1344. This workitem checks the idle state of the device
  1345. and submits an idle request.
  1346. Arguments:
  1347. DeviceObject - pointer to device object
  1348. Context - context for the work item.
  1349. Return Value:
  1350. None
  1351. --*/
  1352. {
  1353. PIRP irp;
  1354. NTSTATUS ntStatus;
  1355. PDEVICE_EXTENSION deviceExtension;
  1356. PIO_WORKITEM workItem;
  1357. BulkUsb_DbgPrint(3, ("IdleRequestWorkerRoutine - begins\n"));
  1358. //
  1359. // initialize variables
  1360. //
  1361. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1362. workItem = (PIO_WORKITEM) Context;
  1363. if(CanDeviceSuspend(deviceExtension)) {
  1364. BulkUsb_DbgPrint(3, ("Device is idle\n"));
  1365. ntStatus = SubmitIdleRequestIrp(deviceExtension);
  1366. if(!NT_SUCCESS(ntStatus)) {
  1367. BulkUsb_DbgPrint(1, ("SubmitIdleRequestIrp failed\n"));
  1368. }
  1369. }
  1370. else {
  1371. BulkUsb_DbgPrint(3, ("Device is not idle\n"));
  1372. }
  1373. IoFreeWorkItem(workItem);
  1374. //
  1375. // signal the NoDpcWorkItemPendingEvent.
  1376. //
  1377. KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent,
  1378. IO_NO_INCREMENT,
  1379. FALSE);
  1380. BulkUsb_DbgPrint(3, ("IdleRequestsWorkerRoutine - ends\n"));
  1381. }
  1382. VOID
  1383. ProcessQueuedRequests(
  1384. IN OUT PDEVICE_EXTENSION DeviceExtension
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Remove and process the entries in the queue. If this routine is called
  1389. when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
  1390. or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
  1391. If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
  1392. are complete with STATUS_DELETE_PENDING
  1393. Arguments:
  1394. DeviceExtension - pointer to device extension
  1395. Return Value:
  1396. None
  1397. --*/
  1398. {
  1399. KIRQL oldIrql;
  1400. PIRP nextIrp,
  1401. cancelledIrp;
  1402. PVOID cancelRoutine;
  1403. LIST_ENTRY cancelledIrpList;
  1404. PLIST_ENTRY listEntry;
  1405. BulkUsb_DbgPrint(3, ("ProcessQueuedRequests - begins\n"));
  1406. //
  1407. // initialize variables
  1408. //
  1409. cancelRoutine = NULL;
  1410. InitializeListHead(&cancelledIrpList);
  1411. //
  1412. // 1. dequeue the entries in the queue
  1413. // 2. reset the cancel routine
  1414. // 3. process them
  1415. // 3a. if the device is active, send them down
  1416. // 3b. else complete with STATUS_DELETE_PENDING
  1417. //
  1418. while(1) {
  1419. KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
  1420. if(IsListEmpty(&DeviceExtension->NewRequestsQueue)) {
  1421. KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
  1422. break;
  1423. }
  1424. //
  1425. // Remove a request from the queue
  1426. //
  1427. listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
  1428. nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
  1429. //
  1430. // set the cancel routine to NULL
  1431. //
  1432. cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
  1433. //
  1434. // check if its already cancelled
  1435. //
  1436. if(nextIrp->Cancel) {
  1437. if(cancelRoutine) {
  1438. //
  1439. // the cancel routine for this IRP hasnt been called yet
  1440. // so queue the IRP in the cancelledIrp list and complete
  1441. // after releasing the lock
  1442. //
  1443. InsertTailList(&cancelledIrpList, listEntry);
  1444. }
  1445. else {
  1446. //
  1447. // the cancel routine has run
  1448. // it must be waiting to hold the queue lock
  1449. // so initialize the IRPs listEntry
  1450. //
  1451. InitializeListHead(listEntry);
  1452. }
  1453. KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
  1454. }
  1455. else {
  1456. KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
  1457. if(FailRequests == DeviceExtension->QueueState) {
  1458. nextIrp->IoStatus.Information = 0;
  1459. nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
  1460. IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
  1461. }
  1462. else {
  1463. PIO_STACK_LOCATION irpStack;
  1464. BulkUsb_DbgPrint(3, ("ProcessQueuedRequests::"));
  1465. BulkUsb_IoIncrement(DeviceExtension);
  1466. IoSkipCurrentIrpStackLocation(nextIrp);
  1467. IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
  1468. BulkUsb_DbgPrint(3, ("ProcessQueuedRequests::"));
  1469. BulkUsb_IoDecrement(DeviceExtension);
  1470. }
  1471. }
  1472. } // while loop
  1473. //
  1474. // walk through the cancelledIrp list and cancel them
  1475. //
  1476. while(!IsListEmpty(&cancelledIrpList)) {
  1477. PLIST_ENTRY cancelEntry = RemoveHeadList(&cancelledIrpList);
  1478. cancelledIrp = CONTAINING_RECORD(cancelEntry, IRP, Tail.Overlay.ListEntry);
  1479. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  1480. cancelledIrp->IoStatus.Information = 0;
  1481. IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
  1482. }
  1483. BulkUsb_DbgPrint(3, ("ProcessQueuedRequests - ends\n"));
  1484. return;
  1485. }
  1486. NTSTATUS
  1487. BulkUsb_GetRegistryDword(
  1488. IN PWCHAR RegPath,
  1489. IN PWCHAR ValueName,
  1490. IN OUT PULONG Value
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. This routine reads the specified reqistry value.
  1495. Arguments:
  1496. RegPath - registry path
  1497. ValueName - property to be fetched from the registry
  1498. Value - corresponding value read from the registry.
  1499. Return Value:
  1500. NT status value
  1501. --*/
  1502. {
  1503. ULONG defaultData;
  1504. WCHAR buffer[MAXIMUM_FILENAME_LENGTH];
  1505. NTSTATUS ntStatus;
  1506. UNICODE_STRING regPath;
  1507. RTL_QUERY_REGISTRY_TABLE paramTable[2];
  1508. BulkUsb_DbgPrint(3, ("BulkUsb_GetRegistryDword - begins\n"));
  1509. regPath.Length = 0;
  1510. regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
  1511. regPath.Buffer = buffer;
  1512. RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
  1513. RtlMoveMemory(regPath.Buffer,
  1514. RegPath,
  1515. wcslen(RegPath) * sizeof(WCHAR));
  1516. RtlZeroMemory(paramTable, sizeof(paramTable));
  1517. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1518. paramTable[0].Name = ValueName;
  1519. paramTable[0].EntryContext = Value;
  1520. paramTable[0].DefaultType = REG_DWORD;
  1521. paramTable[0].DefaultData = &defaultData;
  1522. paramTable[0].DefaultLength = sizeof(ULONG);
  1523. ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
  1524. RTL_REGISTRY_OPTIONAL,
  1525. regPath.Buffer,
  1526. paramTable,
  1527. NULL,
  1528. NULL);
  1529. if(NT_SUCCESS(ntStatus)) {
  1530. BulkUsb_DbgPrint(3, ("success Value = %X\n", *Value));
  1531. return STATUS_SUCCESS;
  1532. }
  1533. else {
  1534. *Value = 0;
  1535. return STATUS_UNSUCCESSFUL;
  1536. }
  1537. }
  1538. NTSTATUS
  1539. BulkUsb_DispatchClean(
  1540. IN PDEVICE_OBJECT DeviceObject,
  1541. IN PIRP Irp
  1542. )
  1543. /*++
  1544. Routine Description:
  1545. Dispatch routine for IRP_MJ_CLEANUP
  1546. Arguments:
  1547. DeviceObject - pointer to device object
  1548. Irp - I/O request packet sent by the pnp manager
  1549. Return Value:
  1550. NT status value
  1551. --*/
  1552. {
  1553. PDEVICE_EXTENSION deviceExtension;
  1554. KIRQL oldIrql;
  1555. LIST_ENTRY cleanupList;
  1556. PLIST_ENTRY thisEntry,
  1557. nextEntry,
  1558. listHead;
  1559. PIRP pendingIrp;
  1560. PIO_STACK_LOCATION pendingIrpStack,
  1561. irpStack;
  1562. NTSTATUS ntStatus;
  1563. //
  1564. // initialize variables
  1565. //
  1566. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1567. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1568. InitializeListHead(&cleanupList);
  1569. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchClean::"));
  1570. BulkUsb_IoIncrement(deviceExtension);
  1571. //
  1572. // acquire queue lock
  1573. //
  1574. KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
  1575. //
  1576. // remove all Irp's that belong to input Irp's fileobject
  1577. //
  1578. listHead = &deviceExtension->NewRequestsQueue;
  1579. for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
  1580. thisEntry != listHead;
  1581. thisEntry = nextEntry, nextEntry = thisEntry->Flink) {
  1582. pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
  1583. pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
  1584. if(irpStack->FileObject == pendingIrpStack->FileObject) {
  1585. RemoveEntryList(thisEntry);
  1586. //
  1587. // set the cancel routine to NULL
  1588. //
  1589. if(NULL == IoSetCancelRoutine(pendingIrp, NULL)) {
  1590. InitializeListHead(thisEntry);
  1591. }
  1592. else {
  1593. InsertTailList(&cleanupList, thisEntry);
  1594. }
  1595. }
  1596. }
  1597. //
  1598. // Release the spin lock
  1599. //
  1600. KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
  1601. //
  1602. // walk thru the cleanup list and cancel all the Irps
  1603. //
  1604. while(!IsListEmpty(&cleanupList)) {
  1605. //
  1606. // complete the Irp
  1607. //
  1608. thisEntry = RemoveHeadList(&cleanupList);
  1609. pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
  1610. pendingIrp->IoStatus.Information = 0;
  1611. pendingIrp->IoStatus.Status = STATUS_CANCELLED;
  1612. IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
  1613. }
  1614. Irp->IoStatus.Information = 0;
  1615. Irp->IoStatus.Status = STATUS_SUCCESS;
  1616. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1617. BulkUsb_DbgPrint(3, ("BulkUsb_DispatchClean::"));
  1618. BulkUsb_IoDecrement(deviceExtension);
  1619. return STATUS_SUCCESS;
  1620. }
  1621. BOOLEAN
  1622. CanDeviceSuspend(
  1623. IN PDEVICE_EXTENSION DeviceExtension
  1624. )
  1625. /*++
  1626. Routine Description:
  1627. This is the routine where we check if the device
  1628. can selectively suspend.
  1629. Arguments:
  1630. DeviceExtension - pointer to device extension
  1631. Return Value:
  1632. TRUE - if the device can suspend
  1633. FALSE - otherwise.
  1634. --*/
  1635. {
  1636. BulkUsb_DbgPrint(3, ("CanDeviceSuspend\n"));
  1637. if((DeviceExtension->OpenHandleCount == 0) &&
  1638. (DeviceExtension->OutStandingIO == 1)) {
  1639. return TRUE;
  1640. }
  1641. else {
  1642. return FALSE;
  1643. }
  1644. }
  1645. NTSTATUS
  1646. BulkUsb_AbortPipes(
  1647. IN PDEVICE_OBJECT DeviceObject
  1648. )
  1649. /*++
  1650. Routine Description
  1651. sends an abort pipe request for open pipes.
  1652. Arguments:
  1653. DeviceObject - pointer to device object
  1654. Return Value:
  1655. NT status value
  1656. --*/
  1657. {
  1658. PURB urb;
  1659. ULONG i;
  1660. NTSTATUS ntStatus;
  1661. PDEVICE_EXTENSION deviceExtension;
  1662. PBULKUSB_PIPE_CONTEXT pipeContext;
  1663. PUSBD_PIPE_INFORMATION pipeInformation;
  1664. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  1665. //
  1666. // initialize variables
  1667. //
  1668. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1669. pipeContext = deviceExtension->PipeContext;
  1670. interfaceInfo = deviceExtension->UsbInterface;
  1671. BulkUsb_DbgPrint(3, ("BulkUsb_AbortPipes - begins\n"));
  1672. if(interfaceInfo == NULL || pipeContext == NULL) {
  1673. return STATUS_SUCCESS;
  1674. }
  1675. for(i=0; i<interfaceInfo->NumberOfPipes; i++) {
  1676. if(pipeContext[i].PipeOpen) {
  1677. BulkUsb_DbgPrint(3, ("Aborting open pipe %d\n", i));
  1678. urb = ExAllocatePool(NonPagedPool,
  1679. sizeof(struct _URB_PIPE_REQUEST));
  1680. if(urb) {
  1681. urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
  1682. urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  1683. urb->UrbPipeRequest.PipeHandle =
  1684. interfaceInfo->Pipes[i].PipeHandle;
  1685. ntStatus = CallUSBD(DeviceObject, urb);
  1686. ExFreePool(urb);
  1687. }
  1688. else {
  1689. BulkUsb_DbgPrint(1, ("Failed to alloc memory for urb\n"));
  1690. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1691. return ntStatus;
  1692. }
  1693. if(NT_SUCCESS(ntStatus)) {
  1694. pipeContext[i].PipeOpen = FALSE;
  1695. }
  1696. }
  1697. }
  1698. BulkUsb_DbgPrint(3, ("BulkUsb_AbortPipes - ends\n"));
  1699. return STATUS_SUCCESS;
  1700. }
  1701. NTSTATUS
  1702. IrpCompletionRoutine(
  1703. IN PDEVICE_OBJECT DeviceObject,
  1704. IN PIRP Irp,
  1705. IN PVOID Context
  1706. )
  1707. /*++
  1708. Routine Description:
  1709. This routine is a completion routine.
  1710. In this routine we set an event.
  1711. Since the completion routine returns
  1712. STATUS_MORE_PROCESSING_REQUIRED, the Irps,
  1713. which set this routine as the completion routine,
  1714. should be marked pending.
  1715. Arguments:
  1716. DeviceObject - pointer to device object
  1717. Irp - I/O request packet
  1718. Context -
  1719. Return Value:
  1720. NT status value
  1721. --*/
  1722. {
  1723. PKEVENT event = Context;
  1724. KeSetEvent(event, 0, FALSE);
  1725. return STATUS_MORE_PROCESSING_REQUIRED;
  1726. }
  1727. LONG
  1728. BulkUsb_IoIncrement(
  1729. IN OUT PDEVICE_EXTENSION DeviceExtension
  1730. )
  1731. /*++
  1732. Routine Description:
  1733. This routine bumps up the I/O count.
  1734. This routine is typically invoked when any of the
  1735. dispatch routines handle new irps for the driver.
  1736. Arguments:
  1737. DeviceExtension - pointer to device extension
  1738. Return Value:
  1739. new value
  1740. --*/
  1741. {
  1742. LONG result = 0;
  1743. KIRQL oldIrql;
  1744. KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
  1745. result = InterlockedIncrement(&DeviceExtension->OutStandingIO);
  1746. //
  1747. // when OutStandingIO bumps from 1 to 2, clear the StopEvent
  1748. //
  1749. if(result == 2) {
  1750. KeClearEvent(&DeviceExtension->StopEvent);
  1751. }
  1752. KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
  1753. BulkUsb_DbgPrint(3, ("BulkUsb_IoIncrement::%d\n", result));
  1754. return result;
  1755. }
  1756. LONG
  1757. BulkUsb_IoDecrement(
  1758. IN OUT PDEVICE_EXTENSION DeviceExtension
  1759. )
  1760. /*++
  1761. Routine Description:
  1762. This routine decrements the outstanding I/O count
  1763. This is typically invoked after the dispatch routine
  1764. has finished processing the irp.
  1765. Arguments:
  1766. DeviceExtension - pointer to device extension
  1767. Return Value:
  1768. new value
  1769. --*/
  1770. {
  1771. LONG result = 0;
  1772. KIRQL oldIrql;
  1773. KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
  1774. result = InterlockedDecrement(&DeviceExtension->OutStandingIO);
  1775. if(result == 1) {
  1776. KeSetEvent(&DeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
  1777. }
  1778. if(result == 0) {
  1779. ASSERT(Removed == DeviceExtension->DeviceState);
  1780. KeSetEvent(&DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
  1781. }
  1782. KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
  1783. BulkUsb_DbgPrint(3, ("BulkUsb_IoDecrement::%d\n", result));
  1784. return result;
  1785. }
  1786. NTSTATUS
  1787. CanStopDevice(
  1788. IN PDEVICE_OBJECT DeviceObject,
  1789. IN PIRP Irp
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. This routine determines whether the device can be safely stopped. In our
  1794. particular case, we'll assume we can always stop the device.
  1795. A device might fail the request if it doesn't have a queue for the
  1796. requests it might come or if it was notified that it is in the paging
  1797. path.
  1798. Arguments:
  1799. DeviceObject - pointer to the device object.
  1800. Irp - pointer to the current IRP.
  1801. Return Value:
  1802. STATUS_SUCCESS if the device can be safely stopped, an appropriate
  1803. NT Status if not.
  1804. --*/
  1805. {
  1806. //
  1807. // We assume we can stop the device
  1808. //
  1809. UNREFERENCED_PARAMETER(DeviceObject);
  1810. UNREFERENCED_PARAMETER(Irp);
  1811. return STATUS_SUCCESS;
  1812. }
  1813. NTSTATUS
  1814. CanRemoveDevice(
  1815. IN PDEVICE_OBJECT DeviceObject,
  1816. IN PIRP Irp
  1817. )
  1818. /*++
  1819. Routine Description:
  1820. This routine determines whether the device can be safely removed. In our
  1821. particular case, we'll assume we can always remove the device.
  1822. A device shouldn't be removed if, for example, it has open handles or
  1823. removing the device could result in losing data (plus the reasons
  1824. mentioned at CanStopDevice). The PnP manager on Windows 2000 fails
  1825. on its own any attempt to remove, if there any open handles to the device.
  1826. However on Win9x, the driver must keep count of open handles and fail
  1827. query_remove if there are any open handles.
  1828. Arguments:
  1829. DeviceObject - pointer to the device object.
  1830. Irp - pointer to the current IRP.
  1831. Return Value:
  1832. STATUS_SUCCESS if the device can be safely removed, an appropriate
  1833. NT Status if not.
  1834. --*/
  1835. {
  1836. //
  1837. // We assume we can remove the device
  1838. //
  1839. UNREFERENCED_PARAMETER(DeviceObject);
  1840. UNREFERENCED_PARAMETER(Irp);
  1841. return STATUS_SUCCESS;
  1842. }
  1843. NTSTATUS
  1844. ReleaseMemory(
  1845. IN PDEVICE_OBJECT DeviceObject
  1846. )
  1847. /*++
  1848. Routine Description:
  1849. This routine returns all the memory allocations acquired during
  1850. device startup.
  1851. Arguments:
  1852. DeviceObject - pointer to the device object.
  1853. Return Value:
  1854. STATUS_SUCCESS if the device can be safely removed, an appropriate
  1855. NT Status if not.
  1856. --*/
  1857. {
  1858. //
  1859. // Disconnect from the interrupt and unmap any I/O ports
  1860. //
  1861. PDEVICE_EXTENSION deviceExtension;
  1862. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1863. if(deviceExtension->UsbConfigurationDescriptor) {
  1864. ExFreePool(deviceExtension->UsbConfigurationDescriptor);
  1865. deviceExtension->UsbConfigurationDescriptor = NULL;
  1866. }
  1867. if(deviceExtension->UsbInterface) {
  1868. ExFreePool(deviceExtension->UsbInterface);
  1869. deviceExtension->UsbInterface = NULL;
  1870. }
  1871. if(deviceExtension->PipeContext) {
  1872. ExFreePool(deviceExtension->PipeContext);
  1873. deviceExtension->PipeContext = NULL;
  1874. }
  1875. return STATUS_SUCCESS;
  1876. }
  1877. PCHAR
  1878. PnPMinorFunctionString (
  1879. UCHAR MinorFunction
  1880. )
  1881. /*++
  1882. Routine Description:
  1883. Arguments:
  1884. Return Value:
  1885. --*/
  1886. {
  1887. switch (MinorFunction) {
  1888. case IRP_MN_START_DEVICE:
  1889. return "IRP_MN_START_DEVICE\n";
  1890. case IRP_MN_QUERY_REMOVE_DEVICE:
  1891. return "IRP_MN_QUERY_REMOVE_DEVICE\n";
  1892. case IRP_MN_REMOVE_DEVICE:
  1893. return "IRP_MN_REMOVE_DEVICE\n";
  1894. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1895. return "IRP_MN_CANCEL_REMOVE_DEVICE\n";
  1896. case IRP_MN_STOP_DEVICE:
  1897. return "IRP_MN_STOP_DEVICE\n";
  1898. case IRP_MN_QUERY_STOP_DEVICE:
  1899. return "IRP_MN_QUERY_STOP_DEVICE\n";
  1900. case IRP_MN_CANCEL_STOP_DEVICE:
  1901. return "IRP_MN_CANCEL_STOP_DEVICE\n";
  1902. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1903. return "IRP_MN_QUERY_DEVICE_RELATIONS\n";
  1904. case IRP_MN_QUERY_INTERFACE:
  1905. return "IRP_MN_QUERY_INTERFACE\n";
  1906. case IRP_MN_QUERY_CAPABILITIES:
  1907. return "IRP_MN_QUERY_CAPABILITIES\n";
  1908. case IRP_MN_QUERY_RESOURCES:
  1909. return "IRP_MN_QUERY_RESOURCES\n";
  1910. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  1911. return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n";
  1912. case IRP_MN_QUERY_DEVICE_TEXT:
  1913. return "IRP_MN_QUERY_DEVICE_TEXT\n";
  1914. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  1915. return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n";
  1916. case IRP_MN_READ_CONFIG:
  1917. return "IRP_MN_READ_CONFIG\n";
  1918. case IRP_MN_WRITE_CONFIG:
  1919. return "IRP_MN_WRITE_CONFIG\n";
  1920. case IRP_MN_EJECT:
  1921. return "IRP_MN_EJECT\n";
  1922. case IRP_MN_SET_LOCK:
  1923. return "IRP_MN_SET_LOCK\n";
  1924. case IRP_MN_QUERY_ID:
  1925. return "IRP_MN_QUERY_ID\n";
  1926. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  1927. return "IRP_MN_QUERY_PNP_DEVICE_STATE\n";
  1928. case IRP_MN_QUERY_BUS_INFORMATION:
  1929. return "IRP_MN_QUERY_BUS_INFORMATION\n";
  1930. case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  1931. return "IRP_MN_DEVICE_USAGE_NOTIFICATION\n";
  1932. case IRP_MN_SURPRISE_REMOVAL:
  1933. return "IRP_MN_SURPRISE_REMOVAL\n";
  1934. default:
  1935. return "IRP_MN_?????\n";
  1936. }
  1937. }