Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

674 lines
17 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract: USB lower filter driver
  6. This module contains the plug and play dispatch entries needed for this
  7. filter.
  8. Author:
  9. Kenneth D. Ray
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <WDM.H>
  15. #include "local.H"
  16. #include "valueadd.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text (PAGE, VA_Power)
  19. #pragma alloc_text (PAGE, VA_PnP)
  20. #pragma alloc_text (PAGE, VA_StartDevice)
  21. #pragma alloc_text (PAGE, VA_StopDevice)
  22. #pragma alloc_text (PAGE, VA_CallUSBD)
  23. #endif
  24. NTSTATUS
  25. VA_Power (
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN PIRP Irp
  28. )
  29. /*++
  30. Routine Description:
  31. The power dispatch routine.
  32. This filter does not recognize power IRPS. It merely sends them down,
  33. unmodified to the next device on the attachment stack.
  34. As this is a POWER irp, and therefore a special irp, special power irp
  35. handling is required.
  36. No completion routine is required.
  37. Arguments:
  38. DeviceObject - pointer to a device object.
  39. Irp - pointer to an I/O Request Packet.
  40. Return Value:
  41. NT status code
  42. --*/
  43. {
  44. PVA_USB_DATA usbData;
  45. NTSTATUS status;
  46. PAGED_CODE ();
  47. TRAP ();
  48. usbData = (PVA_USB_DATA) DeviceObject->DeviceExtension;
  49. if (DeviceObject == Global.ControlObject) {
  50. //
  51. // This irp was sent to the control device object, which knows not
  52. // how to deal with this IRP. It is therefore an error.
  53. //
  54. Irp->IoStatus.Information = 0;
  55. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  56. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  57. return STATUS_NOT_SUPPORTED;
  58. }
  59. //
  60. // This IRP was sent to the filter driver.
  61. // Since we do not know what to do with the IRP, we should pass
  62. // it on along down the stack.
  63. //
  64. InterlockedIncrement (&usbData->OutstandingIO);
  65. if (usbData->Removed) {
  66. status = STATUS_DELETE_PENDING;
  67. PoStartNextPowerIrp (Irp);
  68. Irp->IoStatus.Information = 0;
  69. Irp->IoStatus.Status = status;
  70. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  71. } else {
  72. IoSkipCurrentIrpStackLocation (Irp);
  73. //
  74. // Power IRPS come synchronously; drivers must call
  75. // PoStartNextPowerIrp, when they are ready for the next power irp.
  76. // This can be called here, or in the completetion routine.
  77. //
  78. PoStartNextPowerIrp (Irp);
  79. //
  80. // NOTE!!! PoCallDriver NOT IoCallDriver.
  81. //
  82. status = PoCallDriver (usbData->TopOfStack, Irp);
  83. }
  84. if (0 == InterlockedDecrement (&usbData->OutstandingIO)) {
  85. KeSetEvent (&usbData->RemoveEvent, 0, FALSE);
  86. }
  87. return status;
  88. }
  89. NTSTATUS
  90. VA_PnPComplete (
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN PIRP Irp,
  93. IN PVOID Context
  94. );
  95. NTSTATUS
  96. VA_PnP (
  97. IN PDEVICE_OBJECT DeviceObject,
  98. IN PIRP Irp
  99. )
  100. /*++
  101. Routine Description:
  102. The plug and play dispatch routines.
  103. Most of these this filter driver will completely ignore.
  104. In all cases it must pass on the IRP to the lower driver.
  105. Arguments:
  106. DeviceObject - pointer to a device object.
  107. Irp - pointer to an I/O Request Packet.
  108. Return Value:
  109. NT status code
  110. --*/
  111. {
  112. PVA_USB_DATA usbData;
  113. PIO_STACK_LOCATION stack;
  114. NTSTATUS status;
  115. PVA_CONTROL_DATA controlData;
  116. KIRQL oldIrql;
  117. PAGED_CODE ();
  118. usbData = (PVA_USB_DATA) DeviceObject->DeviceExtension;
  119. stack = IoGetCurrentIrpStackLocation (Irp);
  120. if(DeviceObject == Global.ControlObject) {
  121. //
  122. // This irp was sent to the control device object, which knows not
  123. // how to deal with this IRP. It is therefore an error.
  124. //
  125. Irp->IoStatus.Information = 0;
  126. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  127. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  128. return STATUS_NOT_SUPPORTED;
  129. }
  130. InterlockedIncrement (&usbData->OutstandingIO);
  131. if (usbData->Removed) {
  132. //
  133. // Someone sent us another plug and play IRP after the remove IRP.
  134. // This should never happen.
  135. //
  136. ASSERT (FALSE);
  137. if (0 == InterlockedDecrement (&usbData->OutstandingIO)) {
  138. KeSetEvent (&usbData->RemoveEvent, 0, FALSE);
  139. }
  140. Irp->IoStatus.Information = 0;
  141. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  142. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  143. return STATUS_DELETE_PENDING;
  144. }
  145. switch (stack->MinorFunction) {
  146. case IRP_MN_START_DEVICE:
  147. //
  148. // The device is starting.
  149. //
  150. // We cannot touch the device (send it any non pnp irps) until a
  151. // start device has been passed down to the lower drivers.
  152. //
  153. IoCopyCurrentIrpStackLocationToNext (Irp);
  154. KeInitializeEvent(&usbData->StartEvent, NotificationEvent, FALSE);
  155. IoSetCompletionRoutine (Irp,
  156. VA_PnPComplete,
  157. usbData,
  158. TRUE,
  159. TRUE,
  160. TRUE); // No need for Cancel
  161. status = IoCallDriver (usbData->TopOfStack, Irp);
  162. if (STATUS_PENDING == status) {
  163. KeWaitForSingleObject(
  164. &usbData->StartEvent,
  165. Executive, // Waiting for reason of a driver
  166. KernelMode, // Waiting in kernel mode
  167. FALSE, // No allert
  168. NULL); // No timeout
  169. status = Irp->IoStatus.Status;
  170. }
  171. if (NT_SUCCESS (status)) {
  172. //
  173. // As we are successfully now back from our start device
  174. // we can do work.
  175. //
  176. status = VA_StartDevice (usbData, Irp);
  177. }
  178. //
  179. // We must now complete the IRP, since we stopped it in the
  180. // completetion routine with MORE_PROCESSING_REQUIRED.
  181. //
  182. Irp->IoStatus.Status = status;
  183. Irp->IoStatus.Information = 0;
  184. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  185. break;
  186. case IRP_MN_STOP_DEVICE:
  187. //
  188. // After the start IRP has been sent to the lower driver object, the
  189. // bus may NOT send any more IRPS down ``touch'' until another START
  190. // has occured.
  191. // What ever access is required must be done before the Irp is passed
  192. // on.
  193. //
  194. //
  195. // Do what ever
  196. //
  197. //
  198. // We don't need a completion routine so fire and forget.
  199. //
  200. // Set the current stack location to the next stack location and
  201. // call the next device object.
  202. //
  203. VA_StopDevice (usbData, TRUE);
  204. IoSkipCurrentIrpStackLocation (Irp);
  205. status = IoCallDriver (usbData->TopOfStack, Irp);
  206. break;
  207. case IRP_MN_REMOVE_DEVICE:
  208. //
  209. // The PlugPlay system has dictacted the removal of this device. We
  210. // have no choise but to detach and delete the device objecct.
  211. // (If we wanted to express and interest in preventing this removal,
  212. // we should have filtered the query remove and query stop routines.)
  213. //
  214. // Note! we might receive a remove WITHOUT first receiving a stop.
  215. // ASSERT (!usbData->Removed);
  216. //
  217. // We will no longer receive requests for this device as it has been
  218. // removed.
  219. //
  220. usbData->Removed = TRUE;
  221. if (usbData->Started) {
  222. // Stop the device without touching the hardware.
  223. VA_StopDevice(usbData, FALSE);
  224. }
  225. //
  226. // Here if we had any outstanding requests in a personal queue we should
  227. // complete them all now.
  228. //
  229. // Note, the device is guarenteed stopped, so we cannot send it any non-
  230. // PNP IRPS.
  231. //
  232. controlData = (PVA_CONTROL_DATA) Global.ControlObject->DeviceExtension;
  233. KeAcquireSpinLock (&controlData->Spin, &oldIrql);
  234. RemoveEntryList (&usbData->List);
  235. InterlockedDecrement (&controlData->NumUsbDevices);
  236. KeReleaseSpinLock (&controlData->Spin, oldIrql);
  237. ASSERT (0 < InterlockedDecrement (&usbData->OutstandingIO));
  238. if (0 < InterlockedDecrement (&usbData->OutstandingIO)) {
  239. KeWaitForSingleObject (
  240. &usbData->RemoveEvent,
  241. Executive,
  242. KernelMode,
  243. FALSE,
  244. NULL);
  245. }
  246. //
  247. // Send on the remove IRP
  248. //
  249. IoSkipCurrentIrpStackLocation (Irp);
  250. status = IoCallDriver (usbData->TopOfStack, Irp);
  251. IoDetachDevice (usbData->TopOfStack);
  252. //
  253. // Clean up memory
  254. //
  255. IoDeleteDevice (usbData->Self);
  256. return STATUS_SUCCESS;
  257. case IRP_MN_QUERY_REMOVE_DEVICE:
  258. case IRP_MN_CANCEL_REMOVE_DEVICE:
  259. case IRP_MN_QUERY_STOP_DEVICE:
  260. case IRP_MN_CANCEL_STOP_DEVICE:
  261. case IRP_MN_QUERY_DEVICE_RELATIONS:
  262. case IRP_MN_QUERY_INTERFACE:
  263. case IRP_MN_QUERY_CAPABILITIES:
  264. case IRP_MN_QUERY_RESOURCES:
  265. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  266. case IRP_MN_READ_CONFIG:
  267. case IRP_MN_WRITE_CONFIG:
  268. case IRP_MN_EJECT:
  269. case IRP_MN_SET_LOCK:
  270. case IRP_MN_QUERY_ID:
  271. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  272. default:
  273. //
  274. // Here the filter driver might modify the behavior of these IRPS
  275. // Please see PlugPlay documentation for use of these IRPs.
  276. //
  277. IoSkipCurrentIrpStackLocation (Irp);
  278. status = IoCallDriver (usbData->TopOfStack, Irp);
  279. break;
  280. }
  281. if (0 == InterlockedDecrement (&usbData->OutstandingIO)) {
  282. KeSetEvent (&usbData->RemoveEvent, 0, FALSE);
  283. }
  284. return status;
  285. }
  286. NTSTATUS
  287. VA_PnPComplete (
  288. IN PDEVICE_OBJECT DeviceObject,
  289. IN PIRP Irp,
  290. IN PVOID Context
  291. )
  292. /*++
  293. Routine Description:
  294. The pnp IRP is in the process of completing.
  295. signal
  296. Arguments:
  297. Context set to the device object in question.
  298. --*/
  299. {
  300. PIO_STACK_LOCATION stack;
  301. PVA_USB_DATA usbData;
  302. NTSTATUS status;
  303. UNREFERENCED_PARAMETER (DeviceObject);
  304. status = STATUS_SUCCESS;
  305. usbData = (PVA_USB_DATA) Context;
  306. stack = IoGetCurrentIrpStackLocation (Irp);
  307. if (Irp->PendingReturned) {
  308. IoMarkIrpPending( Irp );
  309. }
  310. switch (stack->MajorFunction) {
  311. case IRP_MJ_PNP:
  312. switch (stack->MinorFunction) {
  313. case IRP_MN_START_DEVICE:
  314. KeSetEvent (&usbData->StartEvent, 0, FALSE);
  315. //
  316. // Take the IRP back so that we can continue using it during
  317. // the IRP_MN_START_DEVICE dispatch routine.
  318. // NB: we will have to call IoCompleteRequest
  319. //
  320. return STATUS_MORE_PROCESSING_REQUIRED;
  321. default:
  322. break;
  323. }
  324. break;
  325. case IRP_MJ_POWER:
  326. default:
  327. break;
  328. }
  329. return status;
  330. }
  331. NTSTATUS
  332. VA_StartDevice (
  333. IN PVA_USB_DATA UsbData,
  334. IN PIRP Irp
  335. )
  336. /*++
  337. Routine Description:
  338. Arguments:
  339. --*/
  340. {
  341. NTSTATUS status;
  342. PURB purb;
  343. struct _URB_CONTROL_DESCRIPTOR_REQUEST urb;
  344. PAGED_CODE();
  345. ASSERT (!UsbData->Removed);
  346. //
  347. // The PlugPlay system should not have started a removed device!
  348. //
  349. if (UsbData->Started) {
  350. return STATUS_SUCCESS;
  351. }
  352. //
  353. // Learn about the device
  354. //
  355. purb = (PURB) &urb;
  356. UsbBuildGetDescriptorRequest (purb,
  357. (USHORT) sizeof (urb),
  358. USB_DEVICE_DESCRIPTOR_TYPE,
  359. 0, // index
  360. 0, // language id
  361. &UsbData->DeviceDesc,
  362. NULL, // no MDL
  363. sizeof (UsbData->DeviceDesc),
  364. NULL); // no linked urbs here
  365. status = VA_CallUSBD (UsbData, purb, Irp);
  366. if (!NT_SUCCESS (status)) {
  367. VA_KdPrint (("Get Device Descriptor failed (%x)\n", status));
  368. TRAP ();
  369. goto VA_START_DEVICE_REJECT;
  370. } else {
  371. VA_KdPrint (("-------------------------\n"));
  372. VA_KdPrint (("Device Descriptor = %x, len %x\n",
  373. &UsbData->DeviceDesc,
  374. urb.TransferBufferLength));
  375. VA_KdPrint (("USB Device Descriptor:\n"));
  376. VA_KdPrint (("bLength %d\n", UsbData->DeviceDesc.bLength));
  377. VA_KdPrint (("bDescriptorType 0x%x\n", UsbData->DeviceDesc.bDescriptorType));
  378. VA_KdPrint (("bcdUSB 0x%x\n", UsbData->DeviceDesc.bcdUSB));
  379. VA_KdPrint (("bDeviceClass 0x%x\n", UsbData->DeviceDesc.bDeviceClass));
  380. VA_KdPrint (("bDeviceSubClass 0x%x\n", UsbData->DeviceDesc.bDeviceSubClass));
  381. VA_KdPrint (("bDeviceProtocol 0x%x\n", UsbData->DeviceDesc.bDeviceProtocol));
  382. VA_KdPrint (("bMaxPacketSize0 0x%x\n", UsbData->DeviceDesc.bMaxPacketSize0));
  383. VA_KdPrint (("idVendor 0x%x\n", UsbData->DeviceDesc.idVendor));
  384. VA_KdPrint (("idProduct 0x%x\n", UsbData->DeviceDesc.idProduct));
  385. VA_KdPrint (("bcdDevice 0x%x\n", UsbData->DeviceDesc.bcdDevice));
  386. VA_KdPrint (("iManufacturer 0x%x\n", UsbData->DeviceDesc.iManufacturer));
  387. VA_KdPrint (("iProduct 0x%x\n", UsbData->DeviceDesc.iProduct));
  388. VA_KdPrint (("iSerialNumber 0x%x\n", UsbData->DeviceDesc.iSerialNumber));
  389. VA_KdPrint (("bNumConfigurations 0x%x\n", UsbData->DeviceDesc.bNumConfigurations));
  390. VA_KdPrint (("-------------------------\n"));
  391. }
  392. return status;
  393. VA_START_DEVICE_REJECT:
  394. //#define CondFree(addr) if ((addr)) ExFreePool ((addr))
  395. // CondFree(usbData->Ppd);
  396. //#undef CondFree
  397. return status;
  398. }
  399. VOID
  400. VA_StopDevice (
  401. IN PVA_USB_DATA UsbData,
  402. IN BOOLEAN TouchTheHardware
  403. )
  404. /*++
  405. Routine Description:
  406. The PlugPlay system has dictacted the removal of this device. We have
  407. no choise but to detach and delete the device objecct.
  408. (If we wanted to express and interest in preventing this removal,
  409. we should have filtered the query remove and query stop routines.)
  410. Note! we might receive a remove WITHOUT first receiving a stop.
  411. Arguments:
  412. UsbData - The device extension for the usb device being started.
  413. TouchTheHardware - Can we actually send non PnP irps to this thing?
  414. --*/
  415. {
  416. TRAP();
  417. PAGED_CODE ();
  418. ASSERT (!UsbData->Removed);
  419. //
  420. // The PlugPlay system should not have started a removed device!
  421. //
  422. if (!UsbData->Started) {
  423. return;
  424. }
  425. if (TouchTheHardware) {
  426. //
  427. // Undo any value add thing required to allow this device to actually
  428. // stop. If there is some shutdown procedure required, or any
  429. // settings required for this device before system shutdown or
  430. // device removal, now is the best time for it.
  431. //
  432. ;
  433. } else {
  434. //
  435. // The device is no longer around, so we cannot actually control it.
  436. // We should instead do what ever necessary in lieu of that.
  437. //
  438. ;
  439. }
  440. UsbData->Started = FALSE;
  441. return;
  442. }
  443. NTSTATUS
  444. VA_Complete (
  445. IN PDEVICE_OBJECT Device,
  446. IN PIRP Irp,
  447. IN PVOID Context
  448. )
  449. /*+
  450. Routine Description:
  451. Get the IRP back
  452. --*/
  453. {
  454. UNREFERENCED_PARAMETER (Device);
  455. KeSetEvent ((PKEVENT) Context, 0, FALSE);
  456. if (Irp->PendingReturned) {
  457. IoMarkIrpPending( Irp );
  458. }
  459. return STATUS_MORE_PROCESSING_REQUIRED;
  460. }
  461. NTSTATUS
  462. VA_CallUSBD(
  463. IN PVA_USB_DATA UsbData,
  464. IN PURB Urb,
  465. IN PIRP Irp
  466. )
  467. /*++
  468. Routine Description:
  469. Synchronously passes a URB to the USBD class driver
  470. This can only be called at PASSIVE_LEVEL and on a thread where you can
  471. wait on an event. (EG a plug play irp)
  472. Arguments:
  473. DeviceObject - pointer to the device object for this instance of an 82930
  474. Urb - pointer to Urb request block
  475. Return Value:
  476. STATUS_SUCCESS if successful,
  477. STATUS_UNSUCCESSFUL otherwise
  478. --*/
  479. {
  480. NTSTATUS status = STATUS_SUCCESS;
  481. KEVENT event;
  482. PIO_STACK_LOCATION nextStack;
  483. PAGED_CODE ();
  484. VA_KdPrint (("enter VA_CallUSBD\n"));
  485. //
  486. // issue a synchronous request
  487. //
  488. KeInitializeEvent(&event, NotificationEvent, FALSE);
  489. //
  490. // Call the class driver to perform the operation. If the returned status
  491. // is PENDING, wait for the request to complete.
  492. //
  493. nextStack = IoGetNextIrpStackLocation(Irp);
  494. ASSERT(nextStack != NULL);
  495. //
  496. // pass the URB to the USB driver stack
  497. //
  498. nextStack->Parameters.Others.Argument1 = Urb;
  499. nextStack->Parameters.DeviceIoControl.IoControlCode =
  500. IOCTL_INTERNAL_USB_SUBMIT_URB;
  501. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  502. IoSetCompletionRoutine (Irp, VA_Complete, &event, TRUE, TRUE, TRUE);
  503. VA_KdPrint (("calling USBD\n"));
  504. status = IoCallDriver(UsbData->TopOfStack, Irp);
  505. VA_KdPrint (("return from IoCallDriver USBD %x\n", status));
  506. if (STATUS_PENDING == status) {
  507. VA_KdPrint (("Wait for single object\n"));
  508. status = KeWaitForSingleObject(
  509. &event,
  510. Suspended,
  511. KernelMode,
  512. FALSE,
  513. NULL);
  514. VA_KdPrint (("KeWait (0x%x)\n", status));
  515. }
  516. VA_KdPrint (("URB status = %x status = %x irp status %x\n",
  517. Urb->UrbHeader.Status, status, Irp->IoStatus.Status));
  518. return Irp->IoStatus.Status;
  519. }