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.

4906 lines
146 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. USBMASS.C
  5. Abstract:
  6. This source file contains the DriverEntry() and AddDevice() entry points
  7. for the USBSTOR driver and the dispatch routines which handle:
  8. IRP_MJ_POWER
  9. IRP_MJ_SYSTEM_CONTROL
  10. IRP_MJ_PNP
  11. Environment:
  12. kernel mode
  13. Revision History:
  14. 06-01-98 : started rewrite
  15. --*/
  16. //*****************************************************************************
  17. // I N C L U D E S
  18. //*****************************************************************************
  19. #include <ntddk.h>
  20. #include <usbdi.h>
  21. #include <usbdlib.h>
  22. #include <initguid.h>
  23. #include <usbbusif.h>
  24. #include <stdio.h>
  25. #include "usbmass.h"
  26. //*****************************************************************************
  27. // L O C A L F U N C T I O N P R O T O T Y P E S
  28. //*****************************************************************************
  29. NTSTATUS
  30. USBSTOR_GetBusInterface (
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PUSB_BUS_INTERFACE_USBDI_V1 BusInterface
  33. );
  34. #ifdef ALLOC_PRAGMA
  35. #pragma alloc_text(PAGE, DriverEntry)
  36. #pragma alloc_text(PAGE, USBSTOR_Unload)
  37. #pragma alloc_text(PAGE, USBSTOR_AddDevice)
  38. #pragma alloc_text(PAGE, USBSTOR_QueryFdoParams)
  39. #pragma alloc_text(PAGE, USBSTOR_Power)
  40. #pragma alloc_text(PAGE, USBSTOR_FdoSetPower)
  41. #pragma alloc_text(PAGE, USBSTOR_SystemControl)
  42. #pragma alloc_text(PAGE, USBSTOR_Pnp)
  43. #pragma alloc_text(PAGE, USBSTOR_FdoStartDevice)
  44. #pragma alloc_text(PAGE, USBSTOR_GetDescriptors)
  45. #pragma alloc_text(PAGE, USBSTOR_GetStringDescriptors)
  46. #pragma alloc_text(PAGE, USBSTOR_AdjustConfigurationDescriptor)
  47. #pragma alloc_text(PAGE, USBSTOR_GetPipes)
  48. #pragma alloc_text(PAGE, USBSTOR_CreateChildPDO)
  49. #pragma alloc_text(PAGE, USBSTOR_FdoStopDevice)
  50. #pragma alloc_text(PAGE, USBSTOR_FdoRemoveDevice)
  51. #pragma alloc_text(PAGE, USBSTOR_FdoQueryStopRemoveDevice)
  52. #pragma alloc_text(PAGE, USBSTOR_FdoCancelStopRemoveDevice)
  53. #pragma alloc_text(PAGE, USBSTOR_FdoQueryDeviceRelations)
  54. #pragma alloc_text(PAGE, USBSTOR_FdoQueryCapabilities)
  55. #pragma alloc_text(PAGE, USBSTOR_PdoStartDevice)
  56. #pragma alloc_text(PAGE, USBSTOR_PdoRemoveDevice)
  57. #pragma alloc_text(PAGE, USBSTOR_PdoQueryID)
  58. #pragma alloc_text(PAGE, USBSTOR_PdoDeviceTypeString)
  59. #pragma alloc_text(PAGE, USBSTOR_PdoGenericTypeString)
  60. #pragma alloc_text(PAGE, CopyField)
  61. #pragma alloc_text(PAGE, USBSTOR_StringArrayToMultiSz)
  62. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceId)
  63. #pragma alloc_text(PAGE, USBSTOR_PdoQueryHardwareIds)
  64. #pragma alloc_text(PAGE, USBSTOR_PdoQueryCompatibleIds)
  65. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceText)
  66. #pragma alloc_text(PAGE, USBSTOR_PdoBusQueryInstanceId)
  67. #pragma alloc_text(PAGE, USBSTOR_PdoQueryDeviceRelations)
  68. #pragma alloc_text(PAGE, USBSTOR_PdoQueryCapabilities)
  69. #pragma alloc_text(PAGE, USBSTOR_SyncPassDownIrp)
  70. #pragma alloc_text(PAGE, USBSTOR_SyncSendUsbRequest)
  71. #pragma alloc_text(PAGE, USBSTOR_GetDescriptor)
  72. #pragma alloc_text(PAGE, USBSTOR_GetMaxLun)
  73. #pragma alloc_text(PAGE, USBSTOR_SelectConfiguration)
  74. #pragma alloc_text(PAGE, USBSTOR_UnConfigure)
  75. #pragma alloc_text(PAGE, USBSTOR_ResetPipe)
  76. #pragma alloc_text(PAGE, USBSTOR_AbortPipe)
  77. #pragma alloc_text(PAGE, USBSTOR_GetBusInterface)
  78. #endif
  79. //******************************************************************************
  80. //
  81. // DriverEntry()
  82. //
  83. //******************************************************************************
  84. NTSTATUS
  85. DriverEntry (
  86. IN PDRIVER_OBJECT DriverObject,
  87. IN PUNICODE_STRING RegistryPath
  88. )
  89. {
  90. PAGED_CODE();
  91. #if DBG
  92. // Query the registry for global parameters
  93. //
  94. USBSTOR_QueryGlobalParams();
  95. #endif
  96. DBGPRINT(2, ("enter: DriverEntry\n"));
  97. DBGFBRK(DBGF_BRK_DRIVERENTRY);
  98. LOGINIT();
  99. //
  100. // Initialize the Driver Object with the driver's entry points
  101. //
  102. //
  103. // USBMASS.C
  104. //
  105. DriverObject->DriverUnload = USBSTOR_Unload;
  106. DriverObject->DriverExtension->AddDevice = USBSTOR_AddDevice;
  107. //
  108. // OCRW.C
  109. //
  110. DriverObject->MajorFunction[IRP_MJ_CREATE] = USBSTOR_Create;
  111. DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBSTOR_Close;
  112. DriverObject->MajorFunction[IRP_MJ_READ] = USBSTOR_ReadWrite;
  113. DriverObject->MajorFunction[IRP_MJ_WRITE] = USBSTOR_ReadWrite;
  114. //
  115. // SCSI.C
  116. //
  117. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBSTOR_DeviceControl;
  118. DriverObject->MajorFunction[IRP_MJ_SCSI] = USBSTOR_Scsi;
  119. DriverObject->DriverStartIo = USBSTOR_StartIo;
  120. //
  121. // USBMASS.C
  122. //
  123. DriverObject->MajorFunction[IRP_MJ_POWER] = USBSTOR_Power;
  124. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBSTOR_SystemControl;
  125. DriverObject->MajorFunction[IRP_MJ_PNP] = USBSTOR_Pnp;
  126. DBGPRINT(2, ("exit: DriverEntry\n"));
  127. return STATUS_SUCCESS;
  128. }
  129. //******************************************************************************
  130. //
  131. // USBSTOR_Unload()
  132. //
  133. //******************************************************************************
  134. VOID
  135. USBSTOR_Unload (
  136. IN PDRIVER_OBJECT DriverObject
  137. )
  138. {
  139. PAGED_CODE();
  140. DBGPRINT(2, ("enter: USBSTOR_Unload\n"));
  141. LOGENTRY('UNLD', DriverObject, 0, 0);
  142. DBGFBRK(DBGF_BRK_UNLOAD);
  143. LOGUNINIT();
  144. DBGPRINT(2, ("exit: USBSTOR_Unload\n"));
  145. }
  146. //******************************************************************************
  147. //
  148. // USBSTOR_AddDevice()
  149. //
  150. //******************************************************************************
  151. NTSTATUS
  152. USBSTOR_AddDevice (
  153. IN PDRIVER_OBJECT DriverObject,
  154. IN PDEVICE_OBJECT PhysicalDeviceObject
  155. )
  156. {
  157. PDEVICE_OBJECT deviceObject;
  158. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  159. NTSTATUS ntStatus;
  160. PAGED_CODE();
  161. DBGPRINT(2, ("enter: USBSTOR_AddDevice\n"));
  162. LOGENTRY('ADDD', DriverObject, PhysicalDeviceObject, 0);
  163. DBGFBRK(DBGF_BRK_ADDDEVICE);
  164. // Create the FDO
  165. //
  166. ntStatus = IoCreateDevice(DriverObject,
  167. sizeof(FDO_DEVICE_EXTENSION),
  168. NULL,
  169. FILE_DEVICE_BUS_EXTENDER,
  170. FILE_AUTOGENERATED_DEVICE_NAME,
  171. FALSE,
  172. &deviceObject);
  173. if (!NT_SUCCESS(ntStatus))
  174. {
  175. return ntStatus;
  176. }
  177. // StartIo should not be called recursively and should be deferred until
  178. // the previous StartIo call returns to the IO manager. This will prevent
  179. // a recursive stack overflow death if a device error occurs when there
  180. // are many requests queued on the device queue.
  181. //
  182. IoSetStartIoAttributes(deviceObject,
  183. TRUE, // DeferredStartIo
  184. FALSE // NonCancelable
  185. );
  186. // Initialize the FDO DeviceExtension
  187. //
  188. fdoDeviceExtension = deviceObject->DeviceExtension;
  189. // Set all DeviceExtension pointers to NULL and all variable to zero
  190. //
  191. RtlZeroMemory(fdoDeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
  192. // Tag this as the FDO on top of the USB PDO
  193. //
  194. fdoDeviceExtension->Type = USBSTOR_DO_TYPE_FDO;
  195. // Store a back point to the DeviceObject to which the DeviceExtension
  196. // is attached.
  197. //
  198. fdoDeviceExtension->FdoDeviceObject = deviceObject;
  199. // Remember our PDO
  200. //
  201. fdoDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  202. // Attach the FDO we created to the top of the PDO stack
  203. //
  204. fdoDeviceExtension->StackDeviceObject = IoAttachDeviceToDeviceStack(
  205. deviceObject,
  206. PhysicalDeviceObject);
  207. // Initialize the list of child PDOs
  208. //
  209. InitializeListHead(&fdoDeviceExtension->ChildPDOs);
  210. // Initialize to one in AddDevice, decrement by one in REMOVE_DEVICE
  211. //
  212. fdoDeviceExtension->PendingIoCount = 1;
  213. // Initialize the event which is set when OpenCount is decremented to zero.
  214. //
  215. KeInitializeEvent(&fdoDeviceExtension->RemoveEvent,
  216. SynchronizationEvent,
  217. FALSE);
  218. // Set the initial system and device power states
  219. //
  220. fdoDeviceExtension->SystemPowerState = PowerSystemWorking;
  221. fdoDeviceExtension->DevicePowerState = PowerDeviceD0;
  222. KeInitializeEvent(&fdoDeviceExtension->PowerDownEvent,
  223. SynchronizationEvent,
  224. FALSE);
  225. // Initialize the spinlock which protects the PDO DeviceFlags
  226. //
  227. KeInitializeSpinLock(&fdoDeviceExtension->ExtensionDataSpinLock);
  228. KeInitializeEvent(&fdoDeviceExtension->CancelEvent,
  229. SynchronizationEvent,
  230. FALSE);
  231. // Initialize timeout timer
  232. //
  233. IoInitializeTimer(deviceObject, USBSTOR_TimerTick, NULL);
  234. USBSTOR_QueryFdoParams(deviceObject);
  235. fdoDeviceExtension->LastSenseWasReset = TRUE;
  236. deviceObject->Flags |= DO_DIRECT_IO;
  237. deviceObject->Flags |= DO_POWER_PAGABLE;
  238. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  239. DBGPRINT(2, ("exit: USBSTOR_AddDevice\n"));
  240. LOGENTRY('addd', deviceObject, fdoDeviceExtension,
  241. fdoDeviceExtension->StackDeviceObject);
  242. return STATUS_SUCCESS;
  243. }
  244. //******************************************************************************
  245. //
  246. // USBSTOR_QueryFdoParams()
  247. //
  248. // This is called at AddDevice() time when the FDO is being created to query
  249. // device parameters from the registry.
  250. //
  251. //******************************************************************************
  252. VOID
  253. USBSTOR_QueryFdoParams (
  254. IN PDEVICE_OBJECT DeviceObject
  255. )
  256. {
  257. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  258. RTL_QUERY_REGISTRY_TABLE paramTable[3];
  259. ULONG driverFlags;
  260. ULONG nonRemovable;
  261. HANDLE handle;
  262. NTSTATUS ntStatus;
  263. PAGED_CODE();
  264. DBGPRINT(2, ("enter: USBSTOR_QueryFdoParams\n"));
  265. fdoDeviceExtension = DeviceObject->DeviceExtension;
  266. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  267. // Set the default value in case the registry key does not exist.
  268. // Currently the flags are only used to specify the device protocol:
  269. // {Bulk-Only, Control/Bulk/Interrupt, Control/Bulk}
  270. //
  271. // If the driver is loaded during textmode setup then the registry key
  272. // will not yet exist. That should be the only case in which the registry
  273. // key does not exist. In this case DeviceProtocolUnspecified will be
  274. // treated as DeviceProtocolCB. If that causes the first request to fail
  275. // then we will switch to DeviceProtocolBulkOnly.
  276. //
  277. driverFlags = DeviceProtocolUnspecified;
  278. nonRemovable = 0;
  279. ntStatus = IoOpenDeviceRegistryKey(
  280. fdoDeviceExtension->PhysicalDeviceObject,
  281. PLUGPLAY_REGKEY_DRIVER,
  282. STANDARD_RIGHTS_ALL,
  283. &handle);
  284. if (NT_SUCCESS(ntStatus))
  285. {
  286. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  287. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  288. paramTable[0].Name = L"DriverFlags";
  289. paramTable[0].EntryContext = &driverFlags;
  290. paramTable[0].DefaultType = REG_BINARY;
  291. paramTable[0].DefaultData = &driverFlags;
  292. paramTable[0].DefaultLength = sizeof(ULONG);
  293. paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  294. paramTable[1].Name = L"NonRemovable";
  295. paramTable[1].EntryContext = &nonRemovable;
  296. paramTable[1].DefaultType = REG_BINARY;
  297. paramTable[1].DefaultData = &nonRemovable;
  298. paramTable[1].DefaultLength = sizeof(ULONG);
  299. RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  300. (PCWSTR)handle,
  301. &paramTable[0],
  302. NULL, // Context
  303. NULL); // Environment
  304. ZwClose(handle);
  305. }
  306. if (driverFlags >= DeviceProtocolLast)
  307. {
  308. driverFlags = DeviceProtocolUnspecified;
  309. }
  310. fdoDeviceExtension->DriverFlags = driverFlags;
  311. fdoDeviceExtension->NonRemovable = nonRemovable;
  312. DBGPRINT(2, ("deviceFlags %08X\n", driverFlags));
  313. DBGPRINT(2, ("nonRemovable %08X\n", nonRemovable));
  314. DBGPRINT(2, ("exit: USBSTOR_QueryFdoParams\n"));
  315. }
  316. //******************************************************************************
  317. //
  318. // USBSTOR_Power()
  319. //
  320. // Dispatch routine which handles IRP_MJ_POWER
  321. //
  322. //******************************************************************************
  323. NTSTATUS
  324. USBSTOR_Power (
  325. IN PDEVICE_OBJECT DeviceObject,
  326. IN PIRP Irp
  327. )
  328. {
  329. PDEVICE_EXTENSION deviceExtension;
  330. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  331. PIO_STACK_LOCATION irpStack;
  332. NTSTATUS ntStatus;
  333. PAGED_CODE();
  334. deviceExtension = DeviceObject->DeviceExtension;
  335. irpStack = IoGetCurrentIrpStackLocation(Irp);
  336. DBGPRINT(2, ("enter: USBSTOR_Power %s %08X %08X %s\n",
  337. (deviceExtension->Type == USBSTOR_DO_TYPE_FDO) ?
  338. "FDO" : "PDO",
  339. DeviceObject,
  340. Irp,
  341. PowerMinorFunctionString(irpStack->MinorFunction)));
  342. LOGENTRY('POWR', DeviceObject, Irp, irpStack->MinorFunction);
  343. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  344. {
  345. DBGPRINT(2, ("%s IRP_MN_SET_POWER %s\n",
  346. (deviceExtension->Type == USBSTOR_DO_TYPE_FDO) ?
  347. "FDO" : "PDO",
  348. (irpStack->Parameters.Power.Type == SystemPowerState) ?
  349. PowerSystemStateString(irpStack->Parameters.Power.State.SystemState) :
  350. PowerDeviceStateString(irpStack->Parameters.Power.State.DeviceState)));
  351. }
  352. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  353. {
  354. // This is an FDO attached to the USB PDO.
  355. //
  356. fdoDeviceExtension = (PFDO_DEVICE_EXTENSION)deviceExtension;
  357. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  358. {
  359. // Handle powering the FDO down and up...
  360. //
  361. ntStatus = USBSTOR_FdoSetPower(DeviceObject,
  362. Irp);
  363. }
  364. else
  365. {
  366. // No special processing for IRP_MN_QUERY_POWER, IRP_MN_WAIT_WAKE,
  367. // or IRP_MN_POWER_SEQUENCE at this time. Just pass the request
  368. // down to the next lower driver now.
  369. //
  370. PoStartNextPowerIrp(Irp);
  371. IoSkipCurrentIrpStackLocation(Irp);
  372. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  373. Irp);
  374. }
  375. }
  376. else
  377. {
  378. // This is a PDO enumerated by our FDO.
  379. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  380. {
  381. // Handle powering the PDO down and up...
  382. //
  383. ntStatus = USBSTOR_PdoSetPower(DeviceObject,
  384. Irp);
  385. }
  386. else
  387. {
  388. if (irpStack->MinorFunction == IRP_MN_QUERY_POWER)
  389. {
  390. // Always return SUCCESS for IRP_MN_QUERY_POWER for the PDO.
  391. //
  392. ntStatus = STATUS_SUCCESS;
  393. Irp->IoStatus.Status = ntStatus;
  394. }
  395. else
  396. {
  397. // No special processing for IRP_MN_WAIT_WAKE or
  398. // IRP_MN_POWER_SEQUENCE. Just complete the request
  399. // now without changing the status.
  400. //
  401. ntStatus = Irp->IoStatus.Status;
  402. }
  403. PoStartNextPowerIrp(Irp);
  404. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  405. }
  406. }
  407. DBGPRINT(2, ("exit: USBSTOR_Power %08X\n", ntStatus));
  408. LOGENTRY('powr', ntStatus, 0, 0);
  409. return ntStatus;
  410. }
  411. //******************************************************************************
  412. //
  413. // USBSTOR_FdoSetPower()
  414. //
  415. // Dispatch routine which handles IRP_MJ_POWER, IRP_MN_SET_POWER for the FDO
  416. //
  417. //******************************************************************************
  418. NTSTATUS
  419. USBSTOR_FdoSetPower (
  420. IN PDEVICE_OBJECT DeviceObject,
  421. IN PIRP Irp
  422. )
  423. {
  424. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  425. PIO_STACK_LOCATION irpStack;
  426. POWER_STATE_TYPE powerType;
  427. POWER_STATE powerState;
  428. POWER_STATE newState;
  429. BOOLEAN passRequest;
  430. NTSTATUS ntStatus;
  431. PAGED_CODE();
  432. fdoDeviceExtension = DeviceObject->DeviceExtension;
  433. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  434. // Get our Irp parameters
  435. //
  436. irpStack = IoGetCurrentIrpStackLocation(Irp);
  437. powerType = irpStack->Parameters.Power.Type;
  438. powerState = irpStack->Parameters.Power.State;
  439. DBGPRINT(2, ("enter: USBSTOR_FdoSetPower %08X %s\n",
  440. DeviceObject,
  441. (powerType == SystemPowerState) ?
  442. PowerSystemStateString(powerState.SystemState) :
  443. PowerDeviceStateString(powerState.DeviceState)));
  444. LOGENTRY('FDSP', DeviceObject, Irp, irpStack->MinorFunction);
  445. // Pass the request down here, unless we request a device state power
  446. // Irp, in which case we pass the request down in our completion routine.
  447. //
  448. passRequest = TRUE;
  449. if (powerType == SystemPowerState)
  450. {
  451. // Remember the current system state.
  452. //
  453. fdoDeviceExtension->SystemPowerState = powerState.SystemState;
  454. // Map the new system state to a new device state
  455. //
  456. if (powerState.SystemState != PowerSystemWorking)
  457. {
  458. newState.DeviceState = PowerDeviceD3;
  459. }
  460. else
  461. {
  462. newState.DeviceState = PowerDeviceD0;
  463. }
  464. // If the new device state is different than the current device
  465. // state, request a device state power Irp.
  466. //
  467. if (fdoDeviceExtension->DevicePowerState != newState.DeviceState)
  468. {
  469. DBGPRINT(2, ("Requesting power Irp %08X %08X from %s to %s\n",
  470. DeviceObject, Irp,
  471. PowerDeviceStateString(fdoDeviceExtension->DevicePowerState),
  472. PowerDeviceStateString(newState.DeviceState)));
  473. ASSERT(fdoDeviceExtension->CurrentPowerIrp == NULL);
  474. fdoDeviceExtension->CurrentPowerIrp = Irp;
  475. ntStatus = PoRequestPowerIrp(fdoDeviceExtension->PhysicalDeviceObject,
  476. IRP_MN_SET_POWER,
  477. newState,
  478. USBSTOR_FdoSetPowerCompletion,
  479. DeviceObject,
  480. NULL);
  481. passRequest = FALSE;
  482. }
  483. }
  484. else if (powerType == DevicePowerState)
  485. {
  486. POWER_STATE oldState;
  487. DBGPRINT(2, ("Received power Irp %08X %08X from %s to %s\n",
  488. DeviceObject, Irp,
  489. PowerDeviceStateString(fdoDeviceExtension->DevicePowerState),
  490. PowerDeviceStateString(powerState.DeviceState)));
  491. // Update the current device state.
  492. //
  493. oldState.DeviceState = fdoDeviceExtension->DevicePowerState;
  494. fdoDeviceExtension->DevicePowerState = powerState.DeviceState;
  495. if (oldState.DeviceState == PowerDeviceD0 &&
  496. powerState.DeviceState > PowerDeviceD0)
  497. {
  498. // Powering down. Stick this Irp in the device queue and
  499. // then wait. When USBSTOR_StartIo() pulls this Irp out
  500. // of the device queue, we'll know that no transfer requests
  501. // are active at that time and then this power Irp can be
  502. // passed down the stack.
  503. ULONG zero;
  504. DBGPRINT(2, ("FDO Powering Down\n"));
  505. LOGENTRY('PWRD', DeviceObject, Irp, 0);
  506. zero = 0; // Front of the queue please
  507. IoStartPacket(DeviceObject,
  508. Irp,
  509. &zero,
  510. NULL);
  511. KeWaitForSingleObject(&fdoDeviceExtension->PowerDownEvent,
  512. Executive,
  513. KernelMode,
  514. FALSE,
  515. NULL);
  516. }
  517. else if (oldState.DeviceState > PowerDeviceD0 &&
  518. powerState.DeviceState == PowerDeviceD0)
  519. {
  520. DBGPRINT(2, ("PDO Powering Up\n"));
  521. LOGENTRY('PWRU', DeviceObject, Irp, 0);
  522. IoCopyCurrentIrpStackLocationToNext(Irp);
  523. IoSetCompletionRoutine(Irp,
  524. USBSTOR_FdoSetPowerD0Completion,
  525. NULL,
  526. TRUE,
  527. TRUE,
  528. TRUE);
  529. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  530. Irp);
  531. passRequest = FALSE;
  532. }
  533. }
  534. if (passRequest)
  535. {
  536. //
  537. // Pass the request down to the next lower driver
  538. //
  539. PoStartNextPowerIrp(Irp);
  540. IoSkipCurrentIrpStackLocation(Irp);
  541. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  542. Irp);
  543. }
  544. DBGPRINT(2, ("exit: USBSTOR_FdoSetPower %08X\n", ntStatus));
  545. LOGENTRY('fdsp', ntStatus, 0, 0);
  546. return ntStatus;
  547. }
  548. //******************************************************************************
  549. //
  550. // USBSTOR_FdoSetPowerCompletion()
  551. //
  552. // Completion routine for PoRequestPowerIrp() in USBSTOR_FdoSetPower.
  553. //
  554. // The purpose of this routine is to block passing down the SystemPowerState
  555. // Irp until the requested DevicePowerState Irp completes.
  556. //
  557. //******************************************************************************
  558. VOID
  559. USBSTOR_FdoSetPowerCompletion(
  560. IN PDEVICE_OBJECT PdoDeviceObject,
  561. IN UCHAR MinorFunction,
  562. IN POWER_STATE PowerState,
  563. IN PVOID Context,
  564. IN PIO_STATUS_BLOCK IoStatus
  565. )
  566. {
  567. PDEVICE_OBJECT fdoDeviceObject;
  568. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  569. PIRP irp;
  570. NTSTATUS ntStatus;
  571. fdoDeviceObject = (PDEVICE_OBJECT)Context;
  572. fdoDeviceExtension = fdoDeviceObject->DeviceExtension;
  573. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  574. ASSERT(fdoDeviceExtension->CurrentPowerIrp != NULL);
  575. irp = fdoDeviceExtension->CurrentPowerIrp;
  576. fdoDeviceExtension->CurrentPowerIrp = NULL;
  577. #if DBG
  578. {
  579. PIO_STACK_LOCATION irpStack;
  580. SYSTEM_POWER_STATE systemState;
  581. irpStack = IoGetCurrentIrpStackLocation(irp);
  582. systemState = irpStack->Parameters.Power.State.SystemState;
  583. ntStatus = IoStatus->Status;
  584. DBGPRINT(2, ("USBSTOR_FdoSetPowerCompletion %08X %08X %s %08X\n",
  585. fdoDeviceObject, irp,
  586. PowerSystemStateString(systemState),
  587. ntStatus));
  588. LOGENTRY('fspc', fdoDeviceObject, systemState, ntStatus);
  589. }
  590. #endif
  591. // The requested DevicePowerState Irp has completed.
  592. // Now pass down the SystemPowerState Irp which requested the
  593. // DevicePowerState Irp.
  594. PoStartNextPowerIrp(irp);
  595. IoCopyCurrentIrpStackLocationToNext(irp);
  596. // Mark the Irp pending since USBSTOR_FdoSetPower() would have
  597. // originally returned STATUS_PENDING after calling PoRequestPowerIrp().
  598. //
  599. IoMarkIrpPending(irp);
  600. ntStatus = PoCallDriver(fdoDeviceExtension->StackDeviceObject,
  601. irp);
  602. }
  603. //******************************************************************************
  604. //
  605. // USBSTOR_FdoSetPowerD0Completion()
  606. //
  607. // Completion routine used by USBSTOR_FdoSetPower when passing down a
  608. // IRP_MN_SET_POWER DevicePowerState PowerDeviceD0 Irp for the FDO.
  609. //
  610. // The purpose of this routine is to delay unblocking the device queue
  611. // until after the DevicePowerState PowerDeviceD0 Irp completes.
  612. //
  613. //******************************************************************************
  614. NTSTATUS
  615. USBSTOR_FdoSetPowerD0Completion (
  616. IN PDEVICE_OBJECT DeviceObject,
  617. IN PIRP Irp,
  618. IN PVOID NotUsed
  619. )
  620. {
  621. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  622. PIO_STACK_LOCATION irpStack;
  623. DEVICE_POWER_STATE deviceState;
  624. KIRQL irql;
  625. NTSTATUS ntStatus;
  626. fdoDeviceExtension = DeviceObject->DeviceExtension;
  627. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  628. irpStack = IoGetCurrentIrpStackLocation(Irp);
  629. deviceState = irpStack->Parameters.Power.State.DeviceState;
  630. ASSERT(deviceState == PowerDeviceD0);
  631. ntStatus = Irp->IoStatus.Status;
  632. DBGPRINT(2, ("USBSTOR_FdoSetPowerD0Completion %08X %08X %s %08X\n",
  633. DeviceObject, Irp,
  634. PowerDeviceStateString(deviceState),
  635. ntStatus));
  636. LOGENTRY('fs0c', DeviceObject, deviceState, ntStatus);
  637. // Powering up. Unblock the device queue which was left blocked
  638. // after USBSTOR_StartIo() passed down the power down Irp.
  639. KeRaiseIrql(DISPATCH_LEVEL, &irql);
  640. {
  641. IoStartNextPacket(DeviceObject, TRUE);
  642. }
  643. KeLowerIrql(irql);
  644. PoStartNextPowerIrp(Irp);
  645. return ntStatus;
  646. }
  647. //******************************************************************************
  648. //
  649. // USBSTOR_PdoSetPower()
  650. //
  651. // Dispatch routine which handles IRP_MJ_POWER, IRP_MN_SET_POWER for the PDO
  652. //
  653. //******************************************************************************
  654. NTSTATUS
  655. USBSTOR_PdoSetPower (
  656. IN PDEVICE_OBJECT DeviceObject,
  657. IN PIRP Irp
  658. )
  659. {
  660. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  661. PIO_STACK_LOCATION irpStack;
  662. POWER_STATE_TYPE powerType;
  663. POWER_STATE powerState;
  664. BOOLEAN completeRequest;
  665. NTSTATUS ntStatus;
  666. pdoDeviceExtension = DeviceObject->DeviceExtension;
  667. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  668. // Get our Irp parameters
  669. //
  670. irpStack = IoGetCurrentIrpStackLocation(Irp);
  671. powerType = irpStack->Parameters.Power.Type;
  672. powerState = irpStack->Parameters.Power.State;
  673. DBGPRINT(2, ("enter: USBSTOR_PdoSetPower %08X %s\n",
  674. DeviceObject,
  675. (powerType == SystemPowerState) ?
  676. PowerSystemStateString(powerState.SystemState) :
  677. PowerDeviceStateString(powerState.DeviceState)));
  678. LOGENTRY('PDSP', DeviceObject, Irp, irpStack->MinorFunction);
  679. // Complete the request here, unless we are powering up or down and need
  680. // to wait before completing the request later.
  681. //
  682. completeRequest = TRUE;
  683. if (powerType == SystemPowerState)
  684. {
  685. POWER_STATE newState;
  686. // Update the current system state.
  687. //
  688. pdoDeviceExtension->SystemPowerState = powerState.SystemState;
  689. // Map the new system state to a new device state
  690. //
  691. if (powerState.SystemState != PowerSystemWorking)
  692. {
  693. newState.DeviceState = PowerDeviceD3;
  694. }
  695. else
  696. {
  697. newState.DeviceState = PowerDeviceD0;
  698. }
  699. // If the new device state is different than the current device
  700. // state, request a device state power Irp.
  701. //
  702. if (pdoDeviceExtension->DevicePowerState != newState.DeviceState)
  703. {
  704. DBGPRINT(2, ("Requesting power Irp %08X %08X from %s to %s\n",
  705. DeviceObject, Irp,
  706. PowerDeviceStateString(pdoDeviceExtension->DevicePowerState),
  707. PowerDeviceStateString(newState.DeviceState)));
  708. ASSERT(pdoDeviceExtension->CurrentPowerIrp == NULL);
  709. pdoDeviceExtension->CurrentPowerIrp = Irp;
  710. ntStatus = PoRequestPowerIrp(DeviceObject,
  711. IRP_MN_SET_POWER,
  712. newState,
  713. USBSTOR_PdoSetPowerCompletion,
  714. NULL,
  715. NULL);
  716. ASSERT(ntStatus == STATUS_PENDING);
  717. completeRequest = FALSE;
  718. }
  719. }
  720. else if (powerType == DevicePowerState)
  721. {
  722. POWER_STATE oldState;
  723. DBGPRINT(2, ("Received power Irp %08X %08X from %s to %s\n",
  724. DeviceObject, Irp,
  725. PowerDeviceStateString(pdoDeviceExtension->DevicePowerState),
  726. PowerDeviceStateString(powerState.DeviceState)));
  727. // Update the current device state.
  728. //
  729. oldState.DeviceState = pdoDeviceExtension->DevicePowerState;
  730. pdoDeviceExtension->DevicePowerState = powerState.DeviceState;
  731. if (oldState.DeviceState == PowerDeviceD0 &&
  732. powerState.DeviceState > PowerDeviceD0)
  733. {
  734. // Powering down.
  735. DBGPRINT(2, ("PDO Powering Down\n"));
  736. LOGENTRY('pwrd', DeviceObject, Irp, 0);
  737. }
  738. else if (oldState.DeviceState > PowerDeviceD0 &&
  739. powerState.DeviceState == PowerDeviceD0)
  740. {
  741. // Powering up.
  742. DBGPRINT(2, ("PDO Powering Up\n"));
  743. LOGENTRY('pwru', DeviceObject, Irp, 0);
  744. }
  745. }
  746. if (completeRequest)
  747. {
  748. ntStatus = STATUS_SUCCESS;
  749. Irp->IoStatus.Status = ntStatus;
  750. PoStartNextPowerIrp(Irp);
  751. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  752. }
  753. DBGPRINT(2, ("exit: USBSTOR_PdoSetPower %08X\n", ntStatus));
  754. LOGENTRY('pdsp', ntStatus, 0, 0);
  755. return ntStatus;
  756. }
  757. //******************************************************************************
  758. //
  759. // USBSTOR_PdoSetPowerCompletion()
  760. //
  761. // Completion routine for PoRequestPowerIrp() in USBSTOR_PdoSetPower.
  762. //
  763. // The purpose of this routine is to block completing the SystemPowerState
  764. // Irp until the requested DevicePowerState Irp completes.
  765. //
  766. //******************************************************************************
  767. VOID
  768. USBSTOR_PdoSetPowerCompletion(
  769. IN PDEVICE_OBJECT DeviceObject,
  770. IN UCHAR MinorFunction,
  771. IN POWER_STATE PowerState,
  772. IN PVOID Context,
  773. IN PIO_STATUS_BLOCK IoStatus
  774. )
  775. {
  776. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  777. PIRP irp;
  778. pdoDeviceExtension = DeviceObject->DeviceExtension;
  779. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  780. ASSERT(pdoDeviceExtension->CurrentPowerIrp != NULL);
  781. irp = pdoDeviceExtension->CurrentPowerIrp;
  782. pdoDeviceExtension->CurrentPowerIrp = NULL;
  783. #if DBG
  784. {
  785. PIO_STACK_LOCATION irpStack;
  786. SYSTEM_POWER_STATE systemState;
  787. NTSTATUS ntStatus;
  788. irpStack = IoGetCurrentIrpStackLocation(irp);
  789. systemState = irpStack->Parameters.Power.State.SystemState;
  790. ntStatus = IoStatus->Status;
  791. DBGPRINT(2, ("USBSTOR_PdoSetPowerCompletion %08X %08X %s %08X\n",
  792. DeviceObject, irp,
  793. PowerSystemStateString(systemState),
  794. ntStatus));
  795. LOGENTRY('pspc', DeviceObject, systemState, ntStatus);
  796. }
  797. #endif
  798. // The requested DevicePowerState Irp has completed.
  799. // Now complete the SystemPowerState Irp which requested the
  800. // DevicePowerState Irp.
  801. // Mark the Irp pending since USBSTOR_PdoSetPower() would have
  802. // originally returned STATUS_PENDING after calling PoRequestPowerIrp().
  803. //
  804. IoMarkIrpPending(irp);
  805. irp->IoStatus.Status = STATUS_SUCCESS;
  806. PoStartNextPowerIrp(irp);
  807. IoCompleteRequest(irp, IO_NO_INCREMENT);
  808. }
  809. //******************************************************************************
  810. //
  811. // USBSTOR_SystemControl()
  812. //
  813. // Dispatch routine which handles IRP_MJ_SYSTEM_CONTROL
  814. //
  815. //******************************************************************************
  816. NTSTATUS
  817. USBSTOR_SystemControl (
  818. IN PDEVICE_OBJECT DeviceObject,
  819. IN PIRP Irp
  820. )
  821. {
  822. PDEVICE_EXTENSION deviceExtension;
  823. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  824. PIO_STACK_LOCATION irpStack;
  825. NTSTATUS ntStatus;
  826. PAGED_CODE();
  827. deviceExtension = DeviceObject->DeviceExtension;
  828. irpStack = IoGetCurrentIrpStackLocation(Irp);
  829. DBGPRINT(2, ("enter: USBSTOR_SystemControl %2X\n", irpStack->MinorFunction));
  830. LOGENTRY('SYSC', DeviceObject, Irp, irpStack->MinorFunction);
  831. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  832. {
  833. // This is an FDO attached to the USB PDO.
  834. //
  835. fdoDeviceExtension = DeviceObject->DeviceExtension;
  836. switch (irpStack->MinorFunction)
  837. {
  838. //
  839. // XXXXX Need to handle any of these?
  840. //
  841. default:
  842. //
  843. // Pass the request down to the next lower driver
  844. //
  845. IoSkipCurrentIrpStackLocation(Irp);
  846. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  847. Irp);
  848. break;
  849. }
  850. }
  851. else
  852. {
  853. // This is a PDO enumerated by our FDO.
  854. ntStatus = Irp->IoStatus.Status;
  855. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  856. }
  857. DBGPRINT(2, ("exit: USBSTOR_SystemControl %08X\n", ntStatus));
  858. LOGENTRY('sysc', ntStatus, 0, 0);
  859. return ntStatus;
  860. }
  861. //******************************************************************************
  862. //
  863. // USBSTOR_Pnp()
  864. //
  865. // Dispatch routine which handles IRP_MJ_PNP
  866. //
  867. //******************************************************************************
  868. NTSTATUS
  869. USBSTOR_Pnp (
  870. IN PDEVICE_OBJECT DeviceObject,
  871. IN PIRP Irp
  872. )
  873. {
  874. PDEVICE_EXTENSION deviceExtension;
  875. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  876. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  877. PIO_STACK_LOCATION irpStack;
  878. NTSTATUS ntStatus;
  879. PAGED_CODE();
  880. deviceExtension = DeviceObject->DeviceExtension;
  881. irpStack = IoGetCurrentIrpStackLocation(Irp);
  882. DBGPRINT(2, ("enter: USBSTOR_Pnp %s\n",
  883. PnPMinorFunctionString(irpStack->MinorFunction)));
  884. LOGENTRY('PNP ', DeviceObject, Irp, irpStack->MinorFunction);
  885. if (deviceExtension->Type == USBSTOR_DO_TYPE_FDO)
  886. {
  887. // This is an FDO attached to the USB PDO.
  888. // We have some real work to do.
  889. //
  890. fdoDeviceExtension = DeviceObject->DeviceExtension;
  891. switch (irpStack->MinorFunction)
  892. {
  893. case IRP_MN_START_DEVICE:
  894. ntStatus = USBSTOR_FdoStartDevice(DeviceObject, Irp);
  895. break;
  896. case IRP_MN_STOP_DEVICE:
  897. ntStatus = USBSTOR_FdoStopDevice(DeviceObject, Irp);
  898. break;
  899. case IRP_MN_REMOVE_DEVICE:
  900. ntStatus = USBSTOR_FdoRemoveDevice(DeviceObject, Irp);
  901. break;
  902. case IRP_MN_QUERY_STOP_DEVICE:
  903. case IRP_MN_QUERY_REMOVE_DEVICE:
  904. ntStatus = USBSTOR_FdoQueryStopRemoveDevice(DeviceObject, Irp);
  905. break;
  906. case IRP_MN_CANCEL_STOP_DEVICE:
  907. case IRP_MN_CANCEL_REMOVE_DEVICE:
  908. ntStatus = USBSTOR_FdoCancelStopRemoveDevice(DeviceObject, Irp);
  909. break;
  910. case IRP_MN_QUERY_DEVICE_RELATIONS:
  911. ntStatus = USBSTOR_FdoQueryDeviceRelations(DeviceObject, Irp);
  912. break;
  913. case IRP_MN_QUERY_CAPABILITIES:
  914. ntStatus = USBSTOR_FdoQueryCapabilities(DeviceObject, Irp);
  915. break;
  916. case IRP_MN_SURPRISE_REMOVAL:
  917. //
  918. // The documentation says to set the status before passing the
  919. // Irp down the stack
  920. //
  921. Irp->IoStatus.Status = STATUS_SUCCESS;
  922. // nothing else special yet, just fall through to default
  923. default:
  924. //
  925. // Pass the request down to the next lower driver
  926. //
  927. IoSkipCurrentIrpStackLocation(Irp);
  928. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  929. Irp);
  930. break;
  931. }
  932. }
  933. else
  934. {
  935. // This is a PDO enumerated by our FDO.
  936. // We don't have too much to do.
  937. //
  938. pdoDeviceExtension = DeviceObject->DeviceExtension;
  939. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  940. switch (irpStack->MinorFunction)
  941. {
  942. case IRP_MN_START_DEVICE:
  943. ntStatus = USBSTOR_PdoStartDevice(DeviceObject, Irp);
  944. break;
  945. case IRP_MN_QUERY_ID:
  946. ntStatus = USBSTOR_PdoQueryID(DeviceObject, Irp);
  947. break;
  948. case IRP_MN_QUERY_DEVICE_TEXT:
  949. ntStatus = USBSTOR_PdoQueryDeviceText(DeviceObject, Irp);
  950. break;
  951. case IRP_MN_QUERY_DEVICE_RELATIONS:
  952. ntStatus = USBSTOR_PdoQueryDeviceRelations(DeviceObject, Irp);
  953. break;
  954. case IRP_MN_QUERY_CAPABILITIES:
  955. ntStatus = USBSTOR_PdoQueryCapabilities(DeviceObject, Irp);
  956. break;
  957. case IRP_MN_REMOVE_DEVICE:
  958. ntStatus = USBSTOR_PdoRemoveDevice(DeviceObject, Irp);
  959. break;
  960. case IRP_MN_SURPRISE_REMOVAL:
  961. case IRP_MN_STOP_DEVICE:
  962. case IRP_MN_QUERY_STOP_DEVICE:
  963. case IRP_MN_QUERY_REMOVE_DEVICE:
  964. case IRP_MN_CANCEL_STOP_DEVICE:
  965. case IRP_MN_CANCEL_REMOVE_DEVICE:
  966. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  967. // We have no value add for IRP_MN_QUERY_PNP_DEVICE_STATE
  968. // at the moment. At some point we might have reason to
  969. // return PNP_DEVICE_REMOVED or PNP_DEVICE_FAILED.
  970. DBGPRINT(2, ("Succeeding PnP for Child PDO %s\n",
  971. PnPMinorFunctionString(irpStack->MinorFunction)));
  972. ntStatus = STATUS_SUCCESS;
  973. Irp->IoStatus.Status = ntStatus;
  974. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  975. break;
  976. default:
  977. DBGPRINT(2, ("Unhandled PnP Irp for Child PDO %s\n",
  978. PnPMinorFunctionString(irpStack->MinorFunction)));
  979. ntStatus = Irp->IoStatus.Status;
  980. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  981. break;
  982. }
  983. }
  984. DBGPRINT(2, ("exit: USBSTOR_Pnp %08X\n", ntStatus));
  985. LOGENTRY('pnp ', ntStatus, 0, 0);
  986. return ntStatus;
  987. }
  988. //******************************************************************************
  989. //
  990. // USBSTOR_FdoStartDevice()
  991. //
  992. // This routine handles IRP_MJ_PNP, IRP_MN_START_DEVICE for the FDO
  993. //
  994. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  995. // system thread.
  996. //
  997. // This IRP must be handled first by the underlying bus driver for a device
  998. // and then by each higher driver in the device stack.
  999. //
  1000. //******************************************************************************
  1001. NTSTATUS
  1002. USBSTOR_FdoStartDevice (
  1003. IN PDEVICE_OBJECT DeviceObject,
  1004. IN PIRP Irp
  1005. )
  1006. {
  1007. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1008. USB_BUS_INTERFACE_USBDI_V1 busInterface;
  1009. NTSTATUS ntStatus;
  1010. PAGED_CODE();
  1011. DBGPRINT(2, ("enter: USBSTOR_FdoStartDevice\n"));
  1012. DBGFBRK(DBGF_BRK_STARTDEVICE);
  1013. LOGENTRY('STRT', DeviceObject, Irp, 0);
  1014. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1015. // Pass IRP_MN_START_DEVICE Irp down the stack first before we do anything.
  1016. //
  1017. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  1018. Irp);
  1019. if (!NT_SUCCESS(ntStatus))
  1020. {
  1021. DBGPRINT(1, ("Lower driver failed IRP_MN_START_DEVICE\n"));
  1022. goto USBSTOR_FdoStartDeviceDone;
  1023. }
  1024. // Allocate Reset Pipe / Reset Port IoWorkItem
  1025. //
  1026. if (fdoDeviceExtension->IoWorkItem == NULL)
  1027. {
  1028. fdoDeviceExtension->IoWorkItem = IoAllocateWorkItem(DeviceObject);
  1029. if (fdoDeviceExtension->IoWorkItem == NULL)
  1030. {
  1031. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1032. goto USBSTOR_FdoStartDeviceDone;
  1033. }
  1034. }
  1035. // If this is the first time the device as been started, retrieve the
  1036. // Device and Configuration Descriptors from the device.
  1037. //
  1038. if (fdoDeviceExtension->DeviceDescriptor == NULL)
  1039. {
  1040. ntStatus = USBSTOR_GetDescriptors(DeviceObject);
  1041. if (!NT_SUCCESS(ntStatus))
  1042. {
  1043. goto USBSTOR_FdoStartDeviceDone;
  1044. }
  1045. }
  1046. // Now configure the device
  1047. //
  1048. ntStatus = USBSTOR_SelectConfiguration(DeviceObject);
  1049. if (!NT_SUCCESS(ntStatus))
  1050. {
  1051. DBGPRINT(1, ("Configure device failed\n"));
  1052. goto USBSTOR_FdoStartDeviceDone;
  1053. }
  1054. // If the driver is loaded during textmode setup then the registry
  1055. // value won't exist yet to indicate what type of device this is. If
  1056. // the Interface Descriptor indicates that the device is a Bulk-Only
  1057. // device then believe it.
  1058. //
  1059. if ((fdoDeviceExtension->InterfaceDescriptor->bInterfaceClass ==
  1060. USB_DEVICE_CLASS_STORAGE) &&
  1061. (fdoDeviceExtension->InterfaceDescriptor->bInterfaceProtocol ==
  1062. USBSTOR_PROTOCOL_BULK_ONLY) &&
  1063. (fdoDeviceExtension->DriverFlags == DeviceProtocolUnspecified))
  1064. {
  1065. fdoDeviceExtension->DriverFlags = DeviceProtocolBulkOnly;
  1066. }
  1067. // Find the bulk and interrupt pipes we'll use in this configuration.
  1068. //
  1069. ntStatus = USBSTOR_GetPipes(DeviceObject);
  1070. if (!NT_SUCCESS(ntStatus))
  1071. {
  1072. goto USBSTOR_FdoStartDeviceDone;
  1073. }
  1074. // Enable hacks for certain revs of the Y-E Data USB Floppy
  1075. //
  1076. if (fdoDeviceExtension->DeviceDescriptor->idVendor == 0x057B &&
  1077. fdoDeviceExtension->DeviceDescriptor->idProduct == 0x0000 &&
  1078. fdoDeviceExtension->DeviceDescriptor->bcdDevice < 0x0128)
  1079. {
  1080. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_FORCE_REQUEST_SENSE);
  1081. #if 0
  1082. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_TUR_START_UNIT);
  1083. SET_FLAG(fdoDeviceExtension->DeviceHackFlags, DHF_MEDIUM_CHANGE_RESET);
  1084. #endif
  1085. }
  1086. // Start timeout timer
  1087. //
  1088. IoStartTimer(DeviceObject);
  1089. // Everything looks good so far, go ahead and create the list of
  1090. // child PDOs if this is the first time we have been started and
  1091. // the list is empty.
  1092. //
  1093. if (IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  1094. {
  1095. UCHAR maxLun;
  1096. UCHAR lun;
  1097. maxLun = 0;
  1098. // Only check devices which claim to be USB Mass Storage Class
  1099. // Bulk-Only spec compliant for Multiple LUN support.
  1100. //
  1101. if ((fdoDeviceExtension->InterfaceDescriptor->bInterfaceClass ==
  1102. USB_DEVICE_CLASS_STORAGE) &&
  1103. (fdoDeviceExtension->InterfaceDescriptor->bInterfaceProtocol ==
  1104. USBSTOR_PROTOCOL_BULK_ONLY))
  1105. {
  1106. // See if the device supports Multiple LUNs
  1107. //
  1108. ntStatus = USBSTOR_GetMaxLun(DeviceObject,
  1109. &maxLun);
  1110. if (NT_SUCCESS(ntStatus))
  1111. {
  1112. DBGPRINT(1, ("GetMaxLun returned %02x\n", maxLun));
  1113. // We need to provide a unique InstanceID for each logical unit.
  1114. // We use the device USB SerialNumber string as part of the
  1115. // unique InstanceID. Without a device USB SerialNumber string
  1116. // we can't support multiple logical units on the device.
  1117. //
  1118. // The Bulk-Only USB Mass Storage class specification requires
  1119. // a SerialNumber string so if the device does not have one it
  1120. // is not really spec compliant anyway.
  1121. //
  1122. if (fdoDeviceExtension->SerialNumber == NULL)
  1123. {
  1124. DBGPRINT(1, ("Multiple Lun but no SerialNumber!\n"));
  1125. maxLun = 0;
  1126. }
  1127. }
  1128. }
  1129. for (lun = 0; lun <= maxLun; lun++)
  1130. {
  1131. ntStatus = USBSTOR_CreateChildPDO(DeviceObject, lun);
  1132. if (!NT_SUCCESS(ntStatus))
  1133. {
  1134. DBGPRINT(1, ("Create Child PDO %d failed\n", lun));
  1135. goto USBSTOR_FdoStartDeviceDone;
  1136. }
  1137. }
  1138. }
  1139. if (NT_SUCCESS(USBSTOR_GetBusInterface(DeviceObject, &busInterface)))
  1140. {
  1141. fdoDeviceExtension->DeviceIsHighSpeed =
  1142. busInterface.IsDeviceHighSpeed(busInterface.BusContext);
  1143. DBGPRINT(1, ("DeviceIsHighSpeed: %s\n",
  1144. fdoDeviceExtension->DeviceIsHighSpeed ? "TRUE" : "FALSE"));
  1145. }
  1146. else
  1147. {
  1148. fdoDeviceExtension->DeviceIsHighSpeed = FALSE;
  1149. }
  1150. USBSTOR_FdoStartDeviceDone:
  1151. // Must complete request since completion routine returned
  1152. // STATUS_MORE_PROCESSING_REQUIRED
  1153. //
  1154. Irp->IoStatus.Status = ntStatus;
  1155. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1156. DBGPRINT(2, ("exit: USBSTOR_FdoStartDevice %08X\n", ntStatus));
  1157. LOGENTRY('strt', ntStatus, 0, 0);
  1158. return ntStatus;
  1159. }
  1160. //******************************************************************************
  1161. //
  1162. // USBSTOR_GetDescriptors()
  1163. //
  1164. // This routine is called at START_DEVICE time for the FDO to retrieve the
  1165. // Device and Configurations descriptors from the device and store them in
  1166. // the device extension.
  1167. //
  1168. //******************************************************************************
  1169. NTSTATUS
  1170. USBSTOR_GetDescriptors (
  1171. IN PDEVICE_OBJECT DeviceObject
  1172. )
  1173. {
  1174. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1175. PUCHAR descriptor;
  1176. ULONG descriptorLength;
  1177. NTSTATUS ntStatus;
  1178. PAGED_CODE();
  1179. DBGPRINT(2, ("enter: USBSTOR_GetDescriptors\n"));
  1180. LOGENTRY('GDSC', DeviceObject, 0, 0);
  1181. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1182. //
  1183. // Get Device Descriptor
  1184. //
  1185. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1186. USB_RECIPIENT_DEVICE,
  1187. USB_DEVICE_DESCRIPTOR_TYPE,
  1188. 0, // Index
  1189. 0, // LanguageId
  1190. 2, // RetryCount
  1191. sizeof(USB_DEVICE_DESCRIPTOR),
  1192. &descriptor);
  1193. if (!NT_SUCCESS(ntStatus))
  1194. {
  1195. DBGPRINT(1, ("Get Device Descriptor failed\n"));
  1196. goto USBSTOR_GetDescriptorsDone;
  1197. }
  1198. ASSERT(fdoDeviceExtension->DeviceDescriptor == NULL);
  1199. fdoDeviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;
  1200. //
  1201. // Get Configuration Descriptor (just the Configuration Descriptor)
  1202. //
  1203. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1204. USB_RECIPIENT_DEVICE,
  1205. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1206. 0, // Index
  1207. 0, // LanguageId
  1208. 2, // RetryCount
  1209. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  1210. &descriptor);
  1211. if (!NT_SUCCESS(ntStatus))
  1212. {
  1213. DBGPRINT(1, ("Get Configuration Descriptor failed (1)\n"));
  1214. goto USBSTOR_GetDescriptorsDone;
  1215. }
  1216. descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;
  1217. ExFreePool(descriptor);
  1218. if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
  1219. {
  1220. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1221. DBGPRINT(1, ("Get Configuration Descriptor failed (2)\n"));
  1222. goto USBSTOR_GetDescriptorsDone;
  1223. }
  1224. //
  1225. // Get Configuration Descriptor (and Interface and Endpoint Descriptors)
  1226. //
  1227. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1228. USB_RECIPIENT_DEVICE,
  1229. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1230. 0, // Index
  1231. 0, // LanguageId
  1232. 2, // RetryCount
  1233. descriptorLength,
  1234. &descriptor);
  1235. if (!NT_SUCCESS(ntStatus))
  1236. {
  1237. DBGPRINT(1, ("Get Configuration Descriptor failed (3)\n"));
  1238. goto USBSTOR_GetDescriptorsDone;
  1239. }
  1240. ASSERT(fdoDeviceExtension->ConfigurationDescriptor == NULL);
  1241. fdoDeviceExtension->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;
  1242. //
  1243. // Get the Serial Number String Descriptor, if there is one
  1244. //
  1245. if (fdoDeviceExtension->DeviceDescriptor->iSerialNumber)
  1246. {
  1247. USBSTOR_GetStringDescriptors(DeviceObject);
  1248. }
  1249. #if DBG
  1250. DumpDeviceDesc(fdoDeviceExtension->DeviceDescriptor);
  1251. DumpConfigDesc(fdoDeviceExtension->ConfigurationDescriptor);
  1252. #endif
  1253. USBSTOR_GetDescriptorsDone:
  1254. DBGPRINT(2, ("exit: USBSTOR_GetDescriptors %08X\n", ntStatus));
  1255. LOGENTRY('gdsc', ntStatus, 0, 0);
  1256. return ntStatus;
  1257. }
  1258. //******************************************************************************
  1259. //
  1260. // USBSTOR_GetStringDescriptors()
  1261. //
  1262. // This routine is called at START_DEVICE time for the FDO to retrieve the
  1263. // Serial Number string descriptor from the device and store it in
  1264. // the device extension.
  1265. //
  1266. //******************************************************************************
  1267. USBSTOR_GetStringDescriptors (
  1268. IN PDEVICE_OBJECT DeviceObject
  1269. )
  1270. {
  1271. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1272. PUCHAR descriptor;
  1273. ULONG descriptorLength;
  1274. USHORT languageId;
  1275. ULONG i, numIds;
  1276. NTSTATUS ntStatus;
  1277. PAGED_CODE();
  1278. DBGPRINT(2, ("enter: USBSTOR_GetStringDescriptors\n"));
  1279. LOGENTRY('GSDC', DeviceObject, 0, 0);
  1280. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1281. //
  1282. // Get the list of Language IDs (descriptor header only)
  1283. //
  1284. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1285. USB_RECIPIENT_DEVICE,
  1286. USB_STRING_DESCRIPTOR_TYPE,
  1287. 0, // Index
  1288. 0, // LanguageId
  1289. 2, // RetryCount
  1290. sizeof(USB_COMMON_DESCRIPTOR),
  1291. &descriptor);
  1292. if (!NT_SUCCESS(ntStatus))
  1293. {
  1294. DBGPRINT(1, ("Get Language IDs failed (1) %08X\n", ntStatus));
  1295. goto USBSTOR_GetStringDescriptorsDone;
  1296. }
  1297. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  1298. ExFreePool(descriptor);
  1299. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  1300. (descriptorLength & 1))
  1301. {
  1302. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1303. DBGPRINT(1, ("Get Language IDs failed (2) %d\n", descriptorLength));
  1304. goto USBSTOR_GetStringDescriptorsDone;
  1305. }
  1306. //
  1307. // Get the list of Language IDs (complete descriptor)
  1308. //
  1309. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1310. USB_RECIPIENT_DEVICE,
  1311. USB_STRING_DESCRIPTOR_TYPE,
  1312. 0, // Index
  1313. 0, // LanguageId
  1314. 2, // RetryCount
  1315. descriptorLength,
  1316. &descriptor);
  1317. if (!NT_SUCCESS(ntStatus))
  1318. {
  1319. DBGPRINT(1, ("Get Language IDs failed (3) %08X\n", ntStatus));
  1320. goto USBSTOR_GetStringDescriptorsDone;
  1321. }
  1322. // Search the list of LanguageIDs for US-English (0x0409). If we find
  1323. // it in the list, that's the LanguageID we'll use. Else just default
  1324. // to the first LanguageID in the list.
  1325. numIds = (descriptorLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(USHORT);
  1326. languageId = ((PUSHORT)descriptor)[1];
  1327. for (i = 2; i <= numIds; i++)
  1328. {
  1329. if (((PUSHORT)descriptor)[i] == 0x0409)
  1330. {
  1331. languageId = 0x0409;
  1332. break;
  1333. }
  1334. }
  1335. ExFreePool(descriptor);
  1336. //
  1337. // Get the Serial Number (descriptor header only)
  1338. //
  1339. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1340. USB_RECIPIENT_DEVICE,
  1341. USB_STRING_DESCRIPTOR_TYPE,
  1342. fdoDeviceExtension->DeviceDescriptor->iSerialNumber,
  1343. languageId,
  1344. 2, // RetryCount
  1345. sizeof(USB_COMMON_DESCRIPTOR),
  1346. &descriptor);
  1347. if (!NT_SUCCESS(ntStatus))
  1348. {
  1349. DBGPRINT(1, ("Get Serial Number failed (1) %08X\n", ntStatus));
  1350. goto USBSTOR_GetStringDescriptorsDone;
  1351. }
  1352. descriptorLength = ((PUSB_COMMON_DESCRIPTOR)descriptor)->bLength;
  1353. ExFreePool(descriptor);
  1354. if ((descriptorLength < sizeof(USB_COMMON_DESCRIPTOR) + sizeof(USHORT)) ||
  1355. (descriptorLength & 1))
  1356. {
  1357. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1358. DBGPRINT(1, ("Get Serial Number failed (2) %d\n", descriptorLength));
  1359. goto USBSTOR_GetStringDescriptorsDone;
  1360. }
  1361. //
  1362. // Get the Serial Number (complete descriptor)
  1363. //
  1364. ntStatus = USBSTOR_GetDescriptor(DeviceObject,
  1365. USB_RECIPIENT_DEVICE,
  1366. USB_STRING_DESCRIPTOR_TYPE,
  1367. fdoDeviceExtension->DeviceDescriptor->iSerialNumber,
  1368. languageId,
  1369. 2, // RetryCount
  1370. descriptorLength,
  1371. &descriptor);
  1372. if (!NT_SUCCESS(ntStatus))
  1373. {
  1374. DBGPRINT(1, ("Get Serial Number failed (3) %08X\n", ntStatus));
  1375. goto USBSTOR_GetStringDescriptorsDone;
  1376. }
  1377. ASSERT(fdoDeviceExtension->SerialNumber == NULL);
  1378. fdoDeviceExtension->SerialNumber = (PUSB_STRING_DESCRIPTOR)descriptor;
  1379. USBSTOR_GetStringDescriptorsDone:
  1380. DBGPRINT(2, ("exit: USBSTOR_GetStringDescriptors %08X %08X\n",
  1381. ntStatus, fdoDeviceExtension->SerialNumber));
  1382. LOGENTRY('gdsc', ntStatus, 0, 0);
  1383. return ntStatus;
  1384. }
  1385. //******************************************************************************
  1386. //
  1387. // USBSTOR_AdjustConfigurationDescriptor()
  1388. //
  1389. // This routine is called at START_DEVICE time for the FDO to adjust the
  1390. // Configuration Descriptor, if necessary.
  1391. //
  1392. // Removes Endpoint Descriptors we won't use. The Configuration Descriptor
  1393. // is modified in place.
  1394. //
  1395. //******************************************************************************
  1396. VOID
  1397. USBSTOR_AdjustConfigurationDescriptor (
  1398. IN PDEVICE_OBJECT DeviceObject,
  1399. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc,
  1400. OUT PUSB_INTERFACE_DESCRIPTOR *InterfaceDesc,
  1401. OUT PLONG BulkInIndex,
  1402. OUT PLONG BulkOutIndex,
  1403. OUT PLONG InterruptInIndex
  1404. )
  1405. {
  1406. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1407. PUCHAR descEnd;
  1408. PUSB_COMMON_DESCRIPTOR commonDesc;
  1409. PUSB_INTERFACE_DESCRIPTOR interfaceDesc;
  1410. PUSB_ENDPOINT_DESCRIPTOR endpointDesc;
  1411. LONG endpointIndex;
  1412. BOOLEAN removeEndpoint;
  1413. PAGED_CODE();
  1414. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1415. descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
  1416. commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
  1417. interfaceDesc = NULL;
  1418. *BulkInIndex = -1;
  1419. *BulkOutIndex = -1;
  1420. *InterruptInIndex = -1;
  1421. endpointIndex = 0;
  1422. while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
  1423. (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
  1424. {
  1425. // Is this an Interface Descriptor?
  1426. //
  1427. if ((commonDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) &&
  1428. (commonDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR)))
  1429. {
  1430. // Only bother looking at the first Interface Descriptor
  1431. //
  1432. if (interfaceDesc != NULL)
  1433. {
  1434. break;
  1435. }
  1436. // Remember the first Interface Descriptor we have seen
  1437. //
  1438. interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)commonDesc;
  1439. }
  1440. // Is this an Endpoint Descriptor?
  1441. //
  1442. if ((commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) &&
  1443. (commonDesc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) &&
  1444. (interfaceDesc != NULL))
  1445. {
  1446. endpointDesc = (PUSB_ENDPOINT_DESCRIPTOR)commonDesc;
  1447. // There is currently a bug in the composite parent driver
  1448. // that doesn't handle the case where the number of
  1449. // endpoints in an Interface Descriptor differs from the
  1450. // Interface Descriptor originally returned by the deivce.
  1451. // Until that bug is fixed avoid the bug by not stripping
  1452. // out endpoints that won't be used.
  1453. //
  1454. removeEndpoint = FALSE;
  1455. if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1456. USB_ENDPOINT_TYPE_BULK) &&
  1457. (USB_ENDPOINT_DIRECTION_IN(endpointDesc->bEndpointAddress)))
  1458. {
  1459. if (*BulkInIndex == -1)
  1460. {
  1461. *BulkInIndex = endpointIndex;
  1462. removeEndpoint = FALSE;
  1463. }
  1464. }
  1465. else if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1466. USB_ENDPOINT_TYPE_BULK) &&
  1467. (USB_ENDPOINT_DIRECTION_OUT(endpointDesc->bEndpointAddress)))
  1468. {
  1469. if (*BulkOutIndex == -1)
  1470. {
  1471. *BulkOutIndex = endpointIndex;
  1472. removeEndpoint = FALSE;
  1473. }
  1474. }
  1475. else if (((endpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
  1476. USB_ENDPOINT_TYPE_INTERRUPT) &&
  1477. (USB_ENDPOINT_DIRECTION_IN(endpointDesc->bEndpointAddress)))
  1478. {
  1479. // Only keep the Interrupt endpoint if we know for sure
  1480. // that the device is a CBI device. Don't trust the
  1481. // bInterfaceProtocol value of the device. Devices can lie.
  1482. //
  1483. if ((*InterruptInIndex == -1) &&
  1484. (fdoDeviceExtension->DriverFlags == DeviceProtocolCBI))
  1485. {
  1486. *InterruptInIndex = endpointIndex;
  1487. removeEndpoint = FALSE;
  1488. }
  1489. }
  1490. if (removeEndpoint)
  1491. {
  1492. // Remove this endpoint, we won't use it.
  1493. //
  1494. DBGPRINT(1, ("Removing Endpoint addr %02X, attr %02X\n",
  1495. endpointDesc->bEndpointAddress,
  1496. endpointDesc->bmAttributes));
  1497. RtlMoveMemory(endpointDesc,
  1498. endpointDesc + 1,
  1499. descEnd - (PUCHAR)(endpointDesc + 1));
  1500. ConfigDesc->wTotalLength -= sizeof(USB_ENDPOINT_DESCRIPTOR);
  1501. interfaceDesc->bNumEndpoints -= 1;
  1502. descEnd -= sizeof(USB_ENDPOINT_DESCRIPTOR);
  1503. continue;
  1504. }
  1505. else
  1506. {
  1507. DBGPRINT(1, ("Keeping Endpoint addr %02X, attr %02X\n",
  1508. endpointDesc->bEndpointAddress,
  1509. endpointDesc->bmAttributes));
  1510. endpointIndex++;
  1511. }
  1512. }
  1513. // Advance past this descriptor
  1514. //
  1515. (PUCHAR)commonDesc += commonDesc->bLength;
  1516. }
  1517. ASSERT(*BulkInIndex != -1);
  1518. ASSERT(*BulkOutIndex != -1);
  1519. ASSERT((*InterruptInIndex != -1) ==
  1520. (fdoDeviceExtension->DriverFlags == DeviceProtocolCBI));
  1521. *InterfaceDesc = interfaceDesc;
  1522. }
  1523. //******************************************************************************
  1524. //
  1525. // USBSTOR_GetPipes()
  1526. //
  1527. // This routine is called at START_DEVICE time find the Bulk IN, Bulk OUT,
  1528. // and Interrupt IN endpoints for the device.
  1529. //
  1530. //******************************************************************************
  1531. NTSTATUS
  1532. USBSTOR_GetPipes (
  1533. IN PDEVICE_OBJECT DeviceObject
  1534. )
  1535. {
  1536. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1537. PUSBD_PIPE_INFORMATION pipe;
  1538. ULONG i;
  1539. NTSTATUS ntStatus;
  1540. PAGED_CODE();
  1541. DBGPRINT(2, ("enter: USBSTOR_GetPipes\n"));
  1542. LOGENTRY('GPIP', DeviceObject, 0, 0);
  1543. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1544. fdoDeviceExtension->BulkInPipe = NULL;
  1545. fdoDeviceExtension->BulkOutPipe = NULL;
  1546. fdoDeviceExtension->InterruptInPipe = NULL;
  1547. // Find the Bulk IN, Bulk OUT, and Interrupt IN endpoints.
  1548. //
  1549. for (i=0; i<fdoDeviceExtension->InterfaceInfo->NumberOfPipes; i++)
  1550. {
  1551. pipe = &fdoDeviceExtension->InterfaceInfo->Pipes[i];
  1552. if (pipe->PipeType == UsbdPipeTypeBulk)
  1553. {
  1554. if (USBD_PIPE_DIRECTION_IN(pipe) &&
  1555. fdoDeviceExtension->BulkInPipe == NULL)
  1556. {
  1557. fdoDeviceExtension->BulkInPipe = pipe;
  1558. }
  1559. else if (!USBD_PIPE_DIRECTION_IN(pipe) &&
  1560. fdoDeviceExtension->BulkOutPipe == NULL)
  1561. {
  1562. fdoDeviceExtension->BulkOutPipe = pipe;
  1563. }
  1564. }
  1565. else if (pipe->PipeType == UsbdPipeTypeInterrupt)
  1566. {
  1567. if (USBD_PIPE_DIRECTION_IN(pipe) &&
  1568. fdoDeviceExtension->InterruptInPipe == NULL &&
  1569. fdoDeviceExtension->DriverFlags == DeviceProtocolCBI)
  1570. {
  1571. fdoDeviceExtension->InterruptInPipe = pipe;
  1572. }
  1573. }
  1574. }
  1575. ntStatus = STATUS_SUCCESS;
  1576. if (fdoDeviceExtension->BulkInPipe == NULL)
  1577. {
  1578. DBGPRINT(1, ("Missing Bulk IN pipe\n"));
  1579. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  1580. }
  1581. if (fdoDeviceExtension->BulkOutPipe == NULL)
  1582. {
  1583. DBGPRINT(1, ("Missing Bulk OUT pipe\n"));
  1584. ntStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
  1585. }
  1586. DBGPRINT(2, ("exit: USBSTOR_GetPipes %08X\n", ntStatus));
  1587. LOGENTRY('gpip', ntStatus, fdoDeviceExtension->BulkInPipe,
  1588. fdoDeviceExtension->BulkOutPipe);
  1589. return ntStatus;
  1590. }
  1591. //******************************************************************************
  1592. //
  1593. // USBSTOR_CreateChildPDO()
  1594. //
  1595. // This routine is called during START_DEVICE of the FDO to create the
  1596. // child PDO. This is only called the first time the FDO is started,
  1597. // after the device has its USB configuration selected.
  1598. //
  1599. //******************************************************************************
  1600. NTSTATUS
  1601. USBSTOR_CreateChildPDO (
  1602. IN PDEVICE_OBJECT FdoDeviceObject,
  1603. IN UCHAR Lun
  1604. )
  1605. {
  1606. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1607. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  1608. PDEVICE_OBJECT pdoDeviceObject;
  1609. NTSTATUS ntStatus;
  1610. PAGED_CODE();
  1611. DBGPRINT(2, ("enter: USBSTOR_CreateChildPDO %d\n", Lun));
  1612. LOGENTRY('CCPD', FdoDeviceObject, Lun, 0);
  1613. fdoDeviceExtension = FdoDeviceObject->DeviceExtension;
  1614. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  1615. // Create the PDO
  1616. //
  1617. ntStatus = IoCreateDevice(FdoDeviceObject->DriverObject,
  1618. sizeof(PDO_DEVICE_EXTENSION),
  1619. NULL,
  1620. FILE_DEVICE_MASS_STORAGE,
  1621. FILE_AUTOGENERATED_DEVICE_NAME,
  1622. FALSE,
  1623. &pdoDeviceObject);
  1624. if (!NT_SUCCESS(ntStatus))
  1625. {
  1626. return ntStatus;
  1627. }
  1628. // The PDO and the FDO are effectively at the same stack level.
  1629. // Irps directed at the PDO will sometimes be passed down with
  1630. // IoCallDriver() to the FDO->StackDeviceObject.
  1631. //
  1632. pdoDeviceObject->StackSize = FdoDeviceObject->StackSize;
  1633. // Initialize the PDO DeviceExtension
  1634. //
  1635. pdoDeviceExtension = pdoDeviceObject->DeviceExtension;
  1636. // Set all DeviceExtension pointers to NULL and all variable to zero
  1637. //
  1638. RtlZeroMemory(pdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
  1639. // Tag this as a PDO which is the child of an FDO
  1640. //
  1641. pdoDeviceExtension->Type = USBSTOR_DO_TYPE_PDO;
  1642. // Point back to our own DeviceObject
  1643. //
  1644. pdoDeviceExtension->PdoDeviceObject = pdoDeviceObject;
  1645. // Remember the PDO's parent FDO
  1646. //
  1647. pdoDeviceExtension->ParentFDO = FdoDeviceObject;
  1648. // Set the initial system and device power states
  1649. //
  1650. pdoDeviceExtension->SystemPowerState = PowerSystemWorking;
  1651. pdoDeviceExtension->DevicePowerState = PowerDeviceD0;
  1652. // Initialize the PDO's PnP device state
  1653. //
  1654. pdoDeviceExtension->DeviceState = DeviceStateCreated;
  1655. // Add the child PDO we just created to the parent's list of child PDOs
  1656. //
  1657. InsertTailList(&fdoDeviceExtension->ChildPDOs,
  1658. &pdoDeviceExtension->ListEntry);
  1659. pdoDeviceObject->Flags |= DO_DIRECT_IO;
  1660. pdoDeviceObject->Flags |= DO_POWER_PAGABLE;
  1661. pdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  1662. pdoDeviceExtension->LUN = Lun;
  1663. // Get the Inquiry Data from the device
  1664. //
  1665. ntStatus = USBSTOR_GetInquiryData(pdoDeviceObject);
  1666. // If the device is a DIRECT_ACCESS_DEVICE, see if it is a floppy
  1667. //
  1668. if (NT_SUCCESS(ntStatus))
  1669. {
  1670. PINQUIRYDATA inquiryData;
  1671. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  1672. if (inquiryData->DeviceType == DIRECT_ACCESS_DEVICE)
  1673. {
  1674. pdoDeviceExtension->IsFloppy = USBSTOR_IsFloppyDevice(pdoDeviceObject);
  1675. }
  1676. }
  1677. DBGPRINT(2, ("exit: USBSTOR_CreateChildPDO %08X\n", ntStatus));
  1678. LOGENTRY('ccpd', FdoDeviceObject, pdoDeviceObject, ntStatus);
  1679. return ntStatus;
  1680. }
  1681. //******************************************************************************
  1682. //
  1683. // USBSTOR_FdoStopDevice()
  1684. //
  1685. // This routine handles IRP_MJ_PNP, IRP_MN_STOP_DEVICE for the FDO
  1686. //
  1687. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1688. // system thread.
  1689. //
  1690. // The PnP Manager only sends this IRP if a prior IRP_MN_QUERY_STOP_DEVICE
  1691. // completed successfully.
  1692. //
  1693. // This IRP is handled first by the driver at the top of the device stack and
  1694. // then by each lower driver in the attachment chain.
  1695. //
  1696. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. A driver must
  1697. // not fail this IRP. If a driver cannot release the device's hardware
  1698. // resources, it can fail a query-stop IRP, but once it succeeds the query-stop
  1699. // request it must succeed the stop request.
  1700. //
  1701. //******************************************************************************
  1702. NTSTATUS
  1703. USBSTOR_FdoStopDevice (
  1704. IN PDEVICE_OBJECT DeviceObject,
  1705. IN PIRP Irp
  1706. )
  1707. {
  1708. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1709. NTSTATUS ntStatus;
  1710. PAGED_CODE();
  1711. DBGPRINT(2, ("enter: USBSTOR_FdoStopDevice\n"));
  1712. LOGENTRY('STOP', DeviceObject, Irp, 0);
  1713. DBGFBRK(DBGF_BRK_STOPDEVICE);
  1714. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1715. // Release the device resources allocated during IRP_MN_START_DEVICE
  1716. //
  1717. // Stop the timeout timer
  1718. //
  1719. IoStopTimer(DeviceObject);
  1720. // Unconfigure the device
  1721. //
  1722. ntStatus = USBSTOR_UnConfigure(DeviceObject);
  1723. // The documentation says to set the status before passing the
  1724. // Irp down the stack
  1725. //
  1726. Irp->IoStatus.Status = STATUS_SUCCESS;
  1727. // Pass the IRP_MN_STOP_DEVICE Irp down the stack.
  1728. //
  1729. IoSkipCurrentIrpStackLocation(Irp);
  1730. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1731. Irp);
  1732. DBGPRINT(2, ("exit: USBSTOR_FdoStopDevice %08X\n", ntStatus));
  1733. LOGENTRY('stop', ntStatus, 0, 0);
  1734. return ntStatus;
  1735. }
  1736. //******************************************************************************
  1737. //
  1738. // USBSTOR_FdoRemoveDevice()
  1739. //
  1740. // This routine handles IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE for the FDO
  1741. //
  1742. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1743. // system thread.
  1744. //
  1745. // This IRP is handled first by the driver at the top of the device stack and
  1746. // then by each lower driver in the attachment chain.
  1747. //
  1748. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. Drivers must not
  1749. // fail this IRP.
  1750. //
  1751. //******************************************************************************
  1752. NTSTATUS
  1753. USBSTOR_FdoRemoveDevice (
  1754. IN PDEVICE_OBJECT DeviceObject,
  1755. IN PIRP Irp
  1756. )
  1757. {
  1758. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1759. NTSTATUS ntStatus;
  1760. PAGED_CODE();
  1761. DBGPRINT(2, ("enter: USBSTOR_FdoRemoveDevice\n"));
  1762. LOGENTRY('REMV', DeviceObject, Irp, 0);
  1763. DBGFBRK(DBGF_BRK_REMOVEDEVICE);
  1764. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1765. // Decrement by one to match the initial one in AddDevice
  1766. //
  1767. DECREMENT_PENDING_IO_COUNT(fdoDeviceExtension);
  1768. LOGENTRY('rem1', DeviceObject, 0, 0);
  1769. // Wait for all pending requests to complete
  1770. //
  1771. KeWaitForSingleObject(&fdoDeviceExtension->RemoveEvent,
  1772. Executive,
  1773. KernelMode,
  1774. FALSE,
  1775. NULL);
  1776. LOGENTRY('rem2', DeviceObject, 0, 0);
  1777. // The child PDOs should have received REMOVE_DEVICE before the FDO.
  1778. // Go ahead and delete them now.
  1779. //
  1780. while (!IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  1781. {
  1782. PLIST_ENTRY listEntry;
  1783. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  1784. listEntry = RemoveTailList(&fdoDeviceExtension->ChildPDOs);
  1785. pdoDeviceExtension = CONTAINING_RECORD(listEntry,
  1786. PDO_DEVICE_EXTENSION,
  1787. ListEntry);
  1788. ASSERT(pdoDeviceExtension->DeviceState == DeviceStateCreated ||
  1789. pdoDeviceExtension->DeviceState == DeviceStateRemoved);
  1790. LOGENTRY('remc', DeviceObject, pdoDeviceExtension->PdoDeviceObject, 0);
  1791. IoDeleteDevice(pdoDeviceExtension->PdoDeviceObject);
  1792. }
  1793. // Free everything that was allocated during IRP_MN_START_DEVICE
  1794. //
  1795. if (fdoDeviceExtension->IoWorkItem != NULL)
  1796. {
  1797. IoFreeWorkItem(fdoDeviceExtension->IoWorkItem);
  1798. }
  1799. if (fdoDeviceExtension->DeviceDescriptor != NULL)
  1800. {
  1801. ExFreePool(fdoDeviceExtension->DeviceDescriptor);
  1802. }
  1803. if (fdoDeviceExtension->ConfigurationDescriptor != NULL)
  1804. {
  1805. ExFreePool(fdoDeviceExtension->ConfigurationDescriptor);
  1806. }
  1807. if (fdoDeviceExtension->SerialNumber != NULL)
  1808. {
  1809. ExFreePool(fdoDeviceExtension->SerialNumber);
  1810. }
  1811. if (fdoDeviceExtension->InterfaceInfo != NULL)
  1812. {
  1813. ExFreePool(fdoDeviceExtension->InterfaceInfo);
  1814. }
  1815. // The documentation says to set the status before passing the Irp down
  1816. //
  1817. Irp->IoStatus.Status = STATUS_SUCCESS;
  1818. // Pass the IRP_MN_REMOVE_DEVICE Irp down the stack.
  1819. //
  1820. IoSkipCurrentIrpStackLocation(Irp);
  1821. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1822. Irp);
  1823. LOGENTRY('rem3', DeviceObject, 0, 0);
  1824. // Free everything that was allocated during AddDevice
  1825. //
  1826. IoDetachDevice(fdoDeviceExtension->StackDeviceObject);
  1827. IoDeleteDevice(DeviceObject);
  1828. DBGPRINT(2, ("exit: USBSTOR_FdoRemoveDevice %08X\n", ntStatus));
  1829. LOGENTRY('remv', ntStatus, 0, 0);
  1830. return ntStatus;
  1831. }
  1832. //******************************************************************************
  1833. //
  1834. // USBSTOR_FdoQueryStopRemoveDevice()
  1835. //
  1836. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE and
  1837. // IRP_MN_QUERY_REMOVE_DEVICE for the FDO.
  1838. //
  1839. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1840. // system thread.
  1841. //
  1842. // This IRP is handled first by the driver at the top of the device stack and
  1843. // then by each lower driver in the attachment chain.
  1844. //
  1845. //******************************************************************************
  1846. NTSTATUS
  1847. USBSTOR_FdoQueryStopRemoveDevice (
  1848. IN PDEVICE_OBJECT DeviceObject,
  1849. IN PIRP Irp
  1850. )
  1851. {
  1852. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1853. NTSTATUS ntStatus;
  1854. PAGED_CODE();
  1855. DBGPRINT(2, ("enter: USBSTOR_FdoQueryStopRemoveDevice\n"));
  1856. LOGENTRY('QSRD', DeviceObject, Irp, 0);
  1857. DBGFBRK(DBGF_BRK_QUERYSTOPDEVICE);
  1858. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1859. // The documentation says to set the status before passing the Irp down
  1860. //
  1861. Irp->IoStatus.Status = STATUS_SUCCESS;
  1862. // Pass the IRP_MN_QUERY_STOP/REMOVE_DEVICE Irp down the stack.
  1863. //
  1864. IoSkipCurrentIrpStackLocation(Irp);
  1865. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  1866. Irp);
  1867. DBGPRINT(2, ("exit: USBSTOR_FdoQueryStopRemoveDevice %08X\n", ntStatus));
  1868. LOGENTRY('qsrd', ntStatus, 0, 0);
  1869. return ntStatus;
  1870. }
  1871. //******************************************************************************
  1872. //
  1873. // USBSTOR_FdoCancelStopRemoveDevice()
  1874. //
  1875. // This routine handles IRP_MJ_PNP, IRP_MN_CANCEL_STOP_DEVICE and
  1876. // IRP_MN_CANCEL_REMOVE_DEVICE for the FDO.
  1877. //
  1878. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1879. // system thread.
  1880. //
  1881. // This IRP must be handled first by the underlying bus driver for a device
  1882. // and then by each higher driver in the device stack.
  1883. //
  1884. //******************************************************************************
  1885. NTSTATUS
  1886. USBSTOR_FdoCancelStopRemoveDevice (
  1887. IN PDEVICE_OBJECT DeviceObject,
  1888. IN PIRP Irp
  1889. )
  1890. {
  1891. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1892. NTSTATUS ntStatus;
  1893. PAGED_CODE();
  1894. DBGPRINT(2, ("enter: USBSTOR_FdoCancelStopRemoveDevice\n"));
  1895. LOGENTRY('CSRD', DeviceObject, Irp, 0);
  1896. DBGFBRK(DBGF_BRK_CANCELSTOPDEVICE);
  1897. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1898. // The documentation says to set the status before passing the Irp down
  1899. //
  1900. Irp->IoStatus.Status = STATUS_SUCCESS;
  1901. // Pass the IRP_MN_CANCEL_STOP/REMOVE_DEVICE Irp down the stack.
  1902. //
  1903. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  1904. Irp);
  1905. if (!NT_SUCCESS(ntStatus))
  1906. {
  1907. DBGPRINT(1, ("Lower driver failed IRP_MN_CANCEL_STOP/REMOVE_DEVICE\n"));
  1908. goto USBSTOR_CancelStopRemoveDeviceDone;
  1909. }
  1910. USBSTOR_CancelStopRemoveDeviceDone:
  1911. // Must complete request since completion routine returned
  1912. // STATUS_MORE_PROCESSING_REQUIRED
  1913. //
  1914. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1915. DBGPRINT(2, ("exit: USBSTOR_FdoCancelStopRemoveDevice %08X\n", ntStatus));
  1916. LOGENTRY('csrd', ntStatus, 0, 0);
  1917. return ntStatus;
  1918. }
  1919. //******************************************************************************
  1920. //
  1921. // USBSTOR_FdoQueryDeviceRelations()
  1922. //
  1923. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS for the FDO.
  1924. //
  1925. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  1926. // an arbitrary thread.
  1927. //
  1928. //******************************************************************************
  1929. NTSTATUS
  1930. USBSTOR_FdoQueryDeviceRelations (
  1931. IN PDEVICE_OBJECT DeviceObject,
  1932. IN PIRP Irp
  1933. )
  1934. {
  1935. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  1936. PIO_STACK_LOCATION irpStack;
  1937. DEVICE_RELATION_TYPE relationType;
  1938. NTSTATUS ntStatus;
  1939. PAGED_CODE();
  1940. fdoDeviceExtension = DeviceObject->DeviceExtension;
  1941. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1942. relationType = irpStack->Parameters.QueryDeviceRelations.Type;
  1943. DBGPRINT(2, ("enter: USBSTOR_FdoQueryDeviceRelations %d\n",
  1944. relationType));
  1945. LOGENTRY('FQDR', DeviceObject, Irp, relationType);
  1946. switch (relationType)
  1947. {
  1948. case BusRelations:
  1949. if (!IsListEmpty(&fdoDeviceExtension->ChildPDOs))
  1950. {
  1951. // If we have children to return, add them to the existing
  1952. // relation list, if there is one, else create and add them
  1953. // to a new relation list.
  1954. //
  1955. // Then in either case, pass the request down the driver stack.
  1956. //
  1957. PDEVICE_RELATIONS oldRelations;
  1958. PDEVICE_RELATIONS newRelations;
  1959. PLIST_ENTRY listHead;
  1960. PLIST_ENTRY listEntry;
  1961. ULONG oldCount;
  1962. ULONG childCount;
  1963. ULONG index;
  1964. listHead = &fdoDeviceExtension->ChildPDOs;
  1965. // How many children?
  1966. //
  1967. for (listEntry = listHead->Flink, childCount = 0;
  1968. listEntry != listHead;
  1969. listEntry = listEntry->Flink, childCount++)
  1970. ;
  1971. oldRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
  1972. if (oldRelations)
  1973. {
  1974. // Add our children to the existing relation list.
  1975. oldCount = oldRelations->Count;
  1976. // A DEVICE_RELATIONS structure has room for one
  1977. // PDEVICE_OBJECT to start with, so subtract that
  1978. // out of the size we allocate.
  1979. //
  1980. newRelations = ExAllocatePoolWithTag(
  1981. PagedPool,
  1982. sizeof(DEVICE_RELATIONS) +
  1983. sizeof(PDEVICE_OBJECT) *
  1984. (oldCount + childCount - 1),
  1985. POOL_TAG);
  1986. if (newRelations)
  1987. {
  1988. // Copy the existing relation list
  1989. //
  1990. for (index = 0; index < oldCount; index++)
  1991. {
  1992. newRelations->Objects[index] =
  1993. oldRelations->Objects[index];
  1994. }
  1995. }
  1996. // Now we're done the the existing relation list, free it
  1997. //
  1998. ExFreePool(oldRelations);
  1999. }
  2000. else
  2001. {
  2002. // Create a new relation list for our children
  2003. newRelations = ExAllocatePoolWithTag(
  2004. PagedPool,
  2005. sizeof(DEVICE_RELATIONS) +
  2006. sizeof(PDEVICE_OBJECT) *
  2007. (childCount - 1),
  2008. POOL_TAG);
  2009. oldCount = 0;
  2010. index = 0;
  2011. }
  2012. if (newRelations)
  2013. {
  2014. newRelations->Count = oldCount + childCount;
  2015. // Add our child relations at the end of the list
  2016. //
  2017. for (listEntry = listHead->Flink;
  2018. listEntry != listHead;
  2019. listEntry = listEntry->Flink)
  2020. {
  2021. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2022. pdoDeviceExtension = CONTAINING_RECORD(
  2023. listEntry,
  2024. PDO_DEVICE_EXTENSION,
  2025. ListEntry);
  2026. newRelations->Objects[index++] =
  2027. pdoDeviceExtension->PdoDeviceObject;
  2028. ObReferenceObject(pdoDeviceExtension->PdoDeviceObject);
  2029. DBGPRINT(2, ("returning ChildPDO %08X\n",
  2030. pdoDeviceExtension->PdoDeviceObject));
  2031. }
  2032. ASSERT(index == oldCount + childCount);
  2033. ntStatus = STATUS_SUCCESS;
  2034. Irp->IoStatus.Status = ntStatus;
  2035. Irp->IoStatus.Information = (ULONG_PTR)newRelations;
  2036. }
  2037. else
  2038. {
  2039. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2040. Irp->IoStatus.Status = ntStatus;
  2041. Irp->IoStatus.Information = 0;
  2042. }
  2043. }
  2044. else
  2045. {
  2046. // If we don't have a child to return, just pass the request
  2047. // down without doing anything.
  2048. //
  2049. ntStatus = STATUS_SUCCESS;
  2050. }
  2051. break;
  2052. case EjectionRelations:
  2053. case PowerRelations:
  2054. case RemovalRelations:
  2055. case TargetDeviceRelation:
  2056. default:
  2057. //
  2058. // Pass the request down the driver stack without doing anything.
  2059. //
  2060. ntStatus = STATUS_SUCCESS;
  2061. break;
  2062. }
  2063. if (NT_SUCCESS(ntStatus))
  2064. {
  2065. // Pass the Irp down the driver stack if successful so far.
  2066. //
  2067. IoSkipCurrentIrpStackLocation(Irp);
  2068. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  2069. Irp);
  2070. }
  2071. else
  2072. {
  2073. // Unsuccessful, just complete the request now.
  2074. //
  2075. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2076. }
  2077. DBGPRINT(2, ("exit: USBSTOR_FdoQueryDeviceRelations %08X\n", ntStatus));
  2078. LOGENTRY('fqdr', ntStatus, 0, 0);
  2079. return ntStatus;
  2080. }
  2081. //******************************************************************************
  2082. //
  2083. // USBSTOR_FdoQueryCapabilities()
  2084. //
  2085. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES for the FDO.
  2086. //
  2087. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2088. // an arbitrary thread.
  2089. //
  2090. //******************************************************************************
  2091. NTSTATUS
  2092. USBSTOR_FdoQueryCapabilities (
  2093. IN PDEVICE_OBJECT DeviceObject,
  2094. IN PIRP Irp
  2095. )
  2096. {
  2097. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2098. PIO_STACK_LOCATION irpStack;
  2099. PDEVICE_CAPABILITIES deviceCapabilities;
  2100. NTSTATUS ntStatus;
  2101. PAGED_CODE();
  2102. fdoDeviceExtension = DeviceObject->DeviceExtension;
  2103. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2104. DBGPRINT(2, ("enter: USBSTOR_FdoQueryCapabilities\n"));
  2105. LOGENTRY('FQCP', DeviceObject, Irp, 0);
  2106. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2107. deviceCapabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  2108. // Pass IRP_MN_QUERY_CAPABILITIES Irp down the stack first before we do
  2109. // anything.
  2110. //
  2111. ntStatus = USBSTOR_SyncPassDownIrp(DeviceObject,
  2112. Irp);
  2113. if (!NT_SUCCESS(ntStatus))
  2114. {
  2115. DBGPRINT(1, ("Lower driver failed IRP_MN_QUERY_CAPABILITIES\n"));
  2116. }
  2117. else
  2118. {
  2119. if (fdoDeviceExtension->NonRemovable)
  2120. {
  2121. deviceCapabilities->Removable = FALSE;
  2122. }
  2123. }
  2124. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2125. DBGPRINT(2, ("exit: USBSTOR_FdoQueryCapabilities %08X\n", ntStatus));
  2126. LOGENTRY('fqcp', ntStatus, 0, 0);
  2127. return ntStatus;
  2128. }
  2129. //******************************************************************************
  2130. //
  2131. // USBSTOR_PdoStartDevice()
  2132. //
  2133. // This routine handles IRP_MJ_PNP, IRP_MN_START_DEVICE for the PDO
  2134. //
  2135. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2136. // system thread.
  2137. //
  2138. //******************************************************************************
  2139. NTSTATUS
  2140. USBSTOR_PdoStartDevice (
  2141. IN PDEVICE_OBJECT DeviceObject,
  2142. IN PIRP Irp
  2143. )
  2144. {
  2145. NTSTATUS ntStatus;
  2146. PAGED_CODE();
  2147. DBGPRINT(2, ("enter: USBSTOR_PdoStartDevice\n"));
  2148. ntStatus = STATUS_SUCCESS;
  2149. Irp->IoStatus.Status = ntStatus;
  2150. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2151. DBGPRINT(2, ("exit: USBSTOR_PdoStartDevice %08X\n", ntStatus));
  2152. LOGENTRY('pstr', ntStatus, 0, 0);
  2153. return ntStatus;
  2154. }
  2155. //******************************************************************************
  2156. //
  2157. // USBSTOR_PdoRemoveDevice()
  2158. //
  2159. // This routine handles IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE for the PDO
  2160. //
  2161. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2162. // system thread.
  2163. //
  2164. //******************************************************************************
  2165. NTSTATUS
  2166. USBSTOR_PdoRemoveDevice (
  2167. IN PDEVICE_OBJECT DeviceObject,
  2168. IN PIRP Irp
  2169. )
  2170. {
  2171. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2172. NTSTATUS ntStatus;
  2173. PAGED_CODE();
  2174. DBGPRINT(2, ("enter: USBSTOR_PdoRemoveDevice\n"));
  2175. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2176. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2177. pdoDeviceExtension->Claimed = FALSE;
  2178. ntStatus = STATUS_SUCCESS;
  2179. Irp->IoStatus.Status = ntStatus;
  2180. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2181. DBGPRINT(2, ("exit: USBSTOR_PdoRemoveDevice %08X\n", ntStatus));
  2182. LOGENTRY('prmd', ntStatus, 0, 0);
  2183. return ntStatus;
  2184. }
  2185. //******************************************************************************
  2186. //
  2187. // USBSTOR_PdoQueryID()
  2188. //
  2189. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_ID for the PDO.
  2190. //
  2191. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2192. // an arbitrary thread.
  2193. //
  2194. //******************************************************************************
  2195. NTSTATUS
  2196. USBSTOR_PdoQueryID (
  2197. IN PDEVICE_OBJECT DeviceObject,
  2198. IN PIRP Irp
  2199. )
  2200. {
  2201. PIO_STACK_LOCATION irpStack;
  2202. UNICODE_STRING unicodeStr;
  2203. BOOLEAN multiStrings;
  2204. NTSTATUS ntStatus;
  2205. PAGED_CODE();
  2206. DBGPRINT(2, ("enter: USBSTOR_PdoQueryID\n"));
  2207. LOGENTRY('PQID', DeviceObject, Irp, 0);
  2208. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2209. // Initialize return value to NULL
  2210. //
  2211. RtlInitUnicodeString(&unicodeStr, NULL);
  2212. switch (irpStack->Parameters.QueryId.IdType)
  2213. {
  2214. case BusQueryDeviceID:
  2215. ntStatus = USBSTOR_PdoQueryDeviceId(
  2216. DeviceObject,
  2217. &unicodeStr);
  2218. multiStrings = FALSE;
  2219. break;
  2220. case BusQueryHardwareIDs:
  2221. ntStatus = USBSTOR_PdoQueryHardwareIds(
  2222. DeviceObject,
  2223. &unicodeStr);
  2224. multiStrings = TRUE;
  2225. break;
  2226. case BusQueryCompatibleIDs:
  2227. ntStatus = USBSTOR_PdoQueryCompatibleIds(
  2228. DeviceObject,
  2229. &unicodeStr);
  2230. multiStrings = TRUE;
  2231. break;
  2232. case BusQueryInstanceID:
  2233. ntStatus = USBSTOR_PdoBusQueryInstanceId(
  2234. DeviceObject,
  2235. &unicodeStr);
  2236. multiStrings = FALSE;
  2237. break;
  2238. default:
  2239. ntStatus = STATUS_NOT_SUPPORTED;
  2240. break;
  2241. }
  2242. if (NT_SUCCESS(ntStatus) && unicodeStr.Buffer)
  2243. {
  2244. PWCHAR idString;
  2245. //
  2246. // fix up all invalid characters
  2247. //
  2248. idString = unicodeStr.Buffer;
  2249. while (*idString)
  2250. {
  2251. if ((*idString <= L' ') ||
  2252. (*idString > (WCHAR)0x7F) ||
  2253. (*idString == L','))
  2254. {
  2255. *idString = L'_';
  2256. }
  2257. idString++;
  2258. if ((*idString == L'\0') && multiStrings)
  2259. {
  2260. idString++;
  2261. }
  2262. }
  2263. Irp->IoStatus.Information = (ULONG_PTR)unicodeStr.Buffer;
  2264. }
  2265. else
  2266. {
  2267. Irp->IoStatus.Information = (ULONG_PTR)NULL;
  2268. }
  2269. Irp->IoStatus.Status = ntStatus;
  2270. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2271. DBGPRINT(2, ("exit: USBSTOR_PdoQueryID %08X\n", ntStatus));
  2272. LOGENTRY('pqid', ntStatus, 0, 0);
  2273. return ntStatus;
  2274. }
  2275. //******************************************************************************
  2276. //
  2277. // USBSTOR_PdoDeviceTypeString()
  2278. //
  2279. // This routine returns a device type string for the PDO.
  2280. //
  2281. //******************************************************************************
  2282. PCHAR
  2283. USBSTOR_PdoDeviceTypeString (
  2284. IN PDEVICE_OBJECT DeviceObject
  2285. )
  2286. {
  2287. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2288. PINQUIRYDATA inquiryData;
  2289. PAGED_CODE();
  2290. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2291. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2292. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2293. switch (inquiryData->DeviceType)
  2294. {
  2295. case DIRECT_ACCESS_DEVICE:
  2296. return pdoDeviceExtension->IsFloppy ? "SFloppy" : "Disk";
  2297. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  2298. return "Worm";
  2299. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  2300. return "CdRom";
  2301. case OPTICAL_DEVICE:
  2302. return "Optical";
  2303. case MEDIUM_CHANGER:
  2304. return "Changer";
  2305. case SEQUENTIAL_ACCESS_DEVICE:
  2306. return "Sequential";
  2307. default:
  2308. return "Other";
  2309. }
  2310. }
  2311. //******************************************************************************
  2312. //
  2313. // USBSTOR_PdoGenericTypeString()
  2314. //
  2315. // This routine returns a device type string for the PDO.
  2316. //
  2317. //******************************************************************************
  2318. PCHAR
  2319. USBSTOR_PdoGenericTypeString (
  2320. IN PDEVICE_OBJECT DeviceObject
  2321. )
  2322. {
  2323. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2324. PINQUIRYDATA inquiryData;
  2325. PAGED_CODE();
  2326. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2327. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2328. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2329. switch (inquiryData->DeviceType)
  2330. {
  2331. case DIRECT_ACCESS_DEVICE:
  2332. return pdoDeviceExtension->IsFloppy ? "GenSFloppy" : "GenDisk";
  2333. case WRITE_ONCE_READ_MULTIPLE_DEVICE:
  2334. return "GenWorm";
  2335. case READ_ONLY_DIRECT_ACCESS_DEVICE:
  2336. return "GenCdRom";
  2337. case OPTICAL_DEVICE:
  2338. return "GenOptical";
  2339. case MEDIUM_CHANGER:
  2340. return "GenChanger";
  2341. case SEQUENTIAL_ACCESS_DEVICE:
  2342. return "GenSequential";
  2343. default:
  2344. return "UsbstorOther";
  2345. }
  2346. }
  2347. //******************************************************************************
  2348. //
  2349. // CopyField()
  2350. //
  2351. // This routine will copy Count string bytes from Source to Destination.
  2352. // If it finds a nul byte in the Source it will translate that and any
  2353. // subsequent bytes into Change. It will also replace spaces with the
  2354. // specified Change character.
  2355. //
  2356. //******************************************************************************
  2357. VOID
  2358. CopyField (
  2359. IN PUCHAR Destination,
  2360. IN PUCHAR Source,
  2361. IN ULONG Count,
  2362. IN UCHAR Change
  2363. )
  2364. {
  2365. ULONG i;
  2366. BOOLEAN pastEnd;
  2367. PAGED_CODE();
  2368. pastEnd = FALSE;
  2369. for (i = 0; i < Count; i++)
  2370. {
  2371. if (!pastEnd)
  2372. {
  2373. if (Source[i] == 0)
  2374. {
  2375. pastEnd = TRUE;
  2376. Destination[i] = Change;
  2377. } else if (Source[i] == ' ')
  2378. {
  2379. Destination[i] = Change;
  2380. } else
  2381. {
  2382. Destination[i] = Source[i];
  2383. }
  2384. }
  2385. else
  2386. {
  2387. Destination[i] = Change;
  2388. }
  2389. }
  2390. return;
  2391. }
  2392. //******************************************************************************
  2393. //
  2394. // USBSTOR_StringArrayToMultiSz()
  2395. //
  2396. // This routine will take a null terminated array of ascii strings and merge
  2397. // them together into a unicode multi-string block.
  2398. //
  2399. // This routine allocates memory for the string buffer - it is the caller's
  2400. // responsibility to free it.
  2401. //
  2402. //******************************************************************************
  2403. NTSTATUS
  2404. USBSTOR_StringArrayToMultiSz(
  2405. PUNICODE_STRING MultiString,
  2406. PCSTR StringArray[]
  2407. )
  2408. {
  2409. ANSI_STRING ansiEntry;
  2410. UNICODE_STRING unicodeEntry;
  2411. UCHAR i;
  2412. NTSTATUS ntStatus;
  2413. PAGED_CODE();
  2414. DBGPRINT(2, ("enter: USBSTOR_StringArrayToMultiSz %08X %08X\n",
  2415. MultiString, StringArray));
  2416. // Make sure we aren't going to leak any memory
  2417. //
  2418. ASSERT(MultiString->Buffer == NULL);
  2419. RtlInitUnicodeString(MultiString, NULL);
  2420. // First add up the sizes of the converted ascii strings to determine
  2421. // how big the multisz will be.
  2422. //
  2423. for (i = 0; StringArray[i] != NULL; i++)
  2424. {
  2425. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  2426. MultiString->Length += (USHORT)RtlAnsiStringToUnicodeSize(&ansiEntry);
  2427. }
  2428. ASSERT(MultiString->Length != 0);
  2429. // Add room for the double NULL terminator
  2430. //
  2431. MultiString->MaximumLength = MultiString->Length + sizeof(UNICODE_NULL);
  2432. // Now allocate a buffer for the multisz
  2433. //
  2434. MultiString->Buffer = ExAllocatePoolWithTag(PagedPool,
  2435. MultiString->MaximumLength,
  2436. POOL_TAG);
  2437. if (MultiString->Buffer == NULL)
  2438. {
  2439. return STATUS_INSUFFICIENT_RESOURCES;
  2440. }
  2441. RtlZeroMemory(MultiString->Buffer, MultiString->MaximumLength);
  2442. unicodeEntry = *MultiString;
  2443. // Now convert each ascii string in the array into a unicode string
  2444. // in the multisz
  2445. //
  2446. for (i = 0; StringArray[i] != NULL; i++)
  2447. {
  2448. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  2449. ntStatus = RtlAnsiStringToUnicodeString(&unicodeEntry,
  2450. &ansiEntry,
  2451. FALSE);
  2452. // Since we're not allocating any memory the only failure possible
  2453. // is if this function is bad
  2454. ASSERT(NT_SUCCESS(ntStatus));
  2455. // Push the buffer location up and reduce the maximum count
  2456. //
  2457. ((PSTR) unicodeEntry.Buffer) += unicodeEntry.Length + sizeof(WCHAR);
  2458. unicodeEntry.MaximumLength -= unicodeEntry.Length + sizeof(WCHAR);
  2459. };
  2460. DBGPRINT(2, ("exit: USBSTOR_StringArrayToMultiSz\n"));
  2461. return STATUS_SUCCESS;
  2462. }
  2463. //******************************************************************************
  2464. //
  2465. // USBSTOR_PdoQueryDeviceId()
  2466. //
  2467. // This routine handles IRP_MN_QUERY_ID BusQueryDeviceID for the PDO.
  2468. //
  2469. //******************************************************************************
  2470. NTSTATUS
  2471. USBSTOR_PdoQueryDeviceId (
  2472. IN PDEVICE_OBJECT DeviceObject,
  2473. OUT PUNICODE_STRING UnicodeString
  2474. )
  2475. {
  2476. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2477. PINQUIRYDATA inquiryData;
  2478. UCHAR buffer[128];
  2479. PUCHAR rawIdString;
  2480. ANSI_STRING ansiIdString;
  2481. ULONG whichString;
  2482. NTSTATUS ntStatus;
  2483. PAGED_CODE();
  2484. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceId\n"));
  2485. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2486. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2487. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2488. RtlZeroMemory(buffer, sizeof(buffer));
  2489. rawIdString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2490. sprintf(buffer, "USBSTOR\\%s", rawIdString);
  2491. rawIdString = buffer + strlen(buffer);
  2492. for (whichString = 0; whichString < 3; whichString++)
  2493. {
  2494. PUCHAR headerString;
  2495. PUCHAR sourceString;
  2496. ULONG sourceStringLength;
  2497. ULONG i;
  2498. switch (whichString)
  2499. {
  2500. //
  2501. // Vendor Id
  2502. //
  2503. case 0:
  2504. sourceString = inquiryData->VendorId;
  2505. sourceStringLength = sizeof(inquiryData->VendorId);
  2506. headerString = "Ven";
  2507. break;
  2508. //
  2509. // Product Id
  2510. //
  2511. case 1:
  2512. sourceString = inquiryData->ProductId;
  2513. sourceStringLength = sizeof(inquiryData->ProductId);
  2514. headerString = "Prod";
  2515. break;
  2516. //
  2517. // Product Revision Level
  2518. //
  2519. case 2:
  2520. sourceString = inquiryData->ProductRevisionLevel;
  2521. sourceStringLength = sizeof(inquiryData->ProductRevisionLevel);
  2522. headerString = "Rev";
  2523. break;
  2524. }
  2525. //
  2526. // Start at the end of the source string and back up until we find a
  2527. // non-space, non-null character.
  2528. //
  2529. for (; sourceStringLength > 0; sourceStringLength--)
  2530. {
  2531. if((sourceString[sourceStringLength - 1] != ' ') &&
  2532. (sourceString[sourceStringLength - 1] != '\0'))
  2533. {
  2534. break;
  2535. }
  2536. }
  2537. //
  2538. // Throw the header string into the block
  2539. //
  2540. sprintf(rawIdString, "&%s_", headerString);
  2541. rawIdString += strlen(headerString) + 2;
  2542. //
  2543. // Spew the string into the device id
  2544. //
  2545. for(i = 0; i < sourceStringLength; i++)
  2546. {
  2547. *rawIdString = (sourceString[i] != ' ') ? (sourceString[i]) :
  2548. ('_');
  2549. rawIdString++;
  2550. }
  2551. }
  2552. RtlInitAnsiString(&ansiIdString, buffer);
  2553. ntStatus = RtlAnsiStringToUnicodeString(UnicodeString, &ansiIdString, TRUE);
  2554. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceId %08X\n", ntStatus));
  2555. return ntStatus;
  2556. }
  2557. //******************************************************************************
  2558. //
  2559. // USBSTOR_PdoQueryHardwareIds()
  2560. //
  2561. // This routine handles IRP_MN_QUERY_ID BusQueryHardwareIDs for the PDO.
  2562. //
  2563. //******************************************************************************
  2564. #define NUMBER_HARDWARE_STRINGS 7
  2565. NTSTATUS
  2566. USBSTOR_PdoQueryHardwareIds (
  2567. IN PDEVICE_OBJECT DeviceObject,
  2568. OUT PUNICODE_STRING UnicodeString
  2569. )
  2570. {
  2571. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2572. PINQUIRYDATA inquiryData;
  2573. PUCHAR devTypeString;
  2574. PUCHAR genTypeString;
  2575. ULONG i;
  2576. PSTR strings[NUMBER_HARDWARE_STRINGS + 1];
  2577. UCHAR scratch[128];
  2578. NTSTATUS ntStatus;
  2579. PAGED_CODE();
  2580. DBGPRINT(2, ("enter: USBSTOR_PdoQueryHardwareIds\n"));
  2581. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2582. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2583. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2584. devTypeString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2585. genTypeString = USBSTOR_PdoGenericTypeString(DeviceObject);
  2586. ntStatus = STATUS_SUCCESS;
  2587. RtlZeroMemory(strings, sizeof(strings));
  2588. for (i = 0; i < NUMBER_HARDWARE_STRINGS; i++)
  2589. {
  2590. RtlZeroMemory(scratch, sizeof(scratch));
  2591. // First build each string in the scratch buffer
  2592. //
  2593. switch (i)
  2594. {
  2595. //
  2596. // Bus + Dev Type + Vendor + Product + Revision
  2597. //
  2598. case 0:
  2599. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2600. CopyField(scratch + strlen(scratch),
  2601. inquiryData->VendorId,
  2602. 8,
  2603. '_');
  2604. CopyField(scratch + strlen(scratch),
  2605. inquiryData->ProductId,
  2606. 16,
  2607. '_');
  2608. CopyField(scratch + strlen(scratch),
  2609. inquiryData->ProductRevisionLevel,
  2610. 4,
  2611. '_');
  2612. break;
  2613. //
  2614. // Bus + Dev Type + Vendor + Product
  2615. //
  2616. case 1:
  2617. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2618. CopyField(scratch + strlen(scratch),
  2619. inquiryData->VendorId,
  2620. 8,
  2621. '_');
  2622. CopyField(scratch + strlen(scratch),
  2623. inquiryData->ProductId,
  2624. 16,
  2625. '_');
  2626. break;
  2627. //
  2628. // Bus + Dev Type + Vendor
  2629. //
  2630. case 2:
  2631. sprintf(scratch, "USBSTOR\\%s", devTypeString);
  2632. CopyField(scratch + strlen(scratch),
  2633. inquiryData->VendorId,
  2634. 8,
  2635. '_');
  2636. break;
  2637. //
  2638. // Bus + Vendor + Product + Revision[0]
  2639. //
  2640. case 3:
  2641. sprintf(scratch, "USBSTOR\\");
  2642. //
  2643. // Fall through to the next set.
  2644. //
  2645. //
  2646. // Vendor + Product + Revision[0] (win9x)
  2647. //
  2648. case 4:
  2649. CopyField(scratch + strlen(scratch),
  2650. inquiryData->VendorId,
  2651. 8,
  2652. '_');
  2653. CopyField(scratch + strlen(scratch),
  2654. inquiryData->ProductId,
  2655. 16,
  2656. '_');
  2657. CopyField(scratch + strlen(scratch),
  2658. inquiryData->ProductRevisionLevel,
  2659. 1,
  2660. '_');
  2661. break;
  2662. //
  2663. // Bus + Generic Type
  2664. //
  2665. case 5:
  2666. sprintf(scratch, "USBSTOR\\%s", genTypeString);
  2667. break;
  2668. //
  2669. // Generic Type
  2670. //
  2671. case 6:
  2672. sprintf(scratch, "%s", genTypeString);
  2673. break;
  2674. default:
  2675. ASSERT(FALSE);
  2676. break;
  2677. }
  2678. // Now allocate a tmp buffer for this string and copy the scratch
  2679. // buffer to the tmp buffer
  2680. //
  2681. if (strlen(scratch) != 0)
  2682. {
  2683. strings[i] = ExAllocatePoolWithTag(
  2684. PagedPool,
  2685. strlen(scratch) + sizeof(UCHAR),
  2686. POOL_TAG);
  2687. if (strings[i] == NULL)
  2688. {
  2689. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2690. break;
  2691. }
  2692. else
  2693. {
  2694. strcpy(strings[i], scratch);
  2695. }
  2696. }
  2697. }
  2698. if (NT_SUCCESS(ntStatus))
  2699. {
  2700. // Now convert the array of stings to one Unicode MultiSz
  2701. //
  2702. ntStatus = USBSTOR_StringArrayToMultiSz(UnicodeString, strings);
  2703. }
  2704. // Now free up the tmp buffers for each string
  2705. //
  2706. for (i = 0; i < NUMBER_HARDWARE_STRINGS; i++)
  2707. {
  2708. if (strings[i])
  2709. {
  2710. ExFreePool(strings[i]);
  2711. }
  2712. }
  2713. DBGPRINT(2, ("exit: USBSTOR_PdoQueryHardwareIds %08X\n", ntStatus));
  2714. return ntStatus;
  2715. }
  2716. //******************************************************************************
  2717. //
  2718. // USBSTOR_PdoQueryCompatibleIds()
  2719. //
  2720. // This routine handles IRP_MN_QUERY_ID BusQueryCompatibleIDs for the PDO.
  2721. //
  2722. //******************************************************************************
  2723. NTSTATUS
  2724. USBSTOR_PdoQueryCompatibleIds (
  2725. IN PDEVICE_OBJECT DeviceObject,
  2726. OUT PUNICODE_STRING UnicodeString
  2727. )
  2728. {
  2729. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2730. PINQUIRYDATA inquiryData;
  2731. PUCHAR devTypeString;
  2732. UCHAR s[sizeof("USBSTOR\\DEVICE_TYPE_GOES_HERE")];
  2733. PSTR strings[] = {s, "USBSTOR\\RAW", NULL};
  2734. NTSTATUS ntStatus;
  2735. PAGED_CODE();
  2736. DBGPRINT(2, ("enter: USBSTOR_PdoQueryCompatibleIds\n"));
  2737. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2738. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2739. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2740. devTypeString = USBSTOR_PdoDeviceTypeString(DeviceObject);
  2741. sprintf(s, "USBSTOR\\%s", devTypeString);
  2742. ntStatus = USBSTOR_StringArrayToMultiSz(UnicodeString, strings);
  2743. DBGPRINT(2, ("exit: USBSTOR_PdoQueryCompatibleIds %08X\n", ntStatus));
  2744. return ntStatus;
  2745. }
  2746. //******************************************************************************
  2747. //
  2748. // USBSTOR_PdoQueryDeviceText()
  2749. //
  2750. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_TEXT for the PDO.
  2751. //
  2752. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2753. // an arbitrary thread.
  2754. //
  2755. //******************************************************************************
  2756. NTSTATUS
  2757. USBSTOR_PdoQueryDeviceText (
  2758. IN PDEVICE_OBJECT DeviceObject,
  2759. IN PIRP Irp
  2760. )
  2761. {
  2762. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2763. PINQUIRYDATA inquiryData;
  2764. PIO_STACK_LOCATION irpStack;
  2765. DEVICE_TEXT_TYPE textType;
  2766. UCHAR ansiBuffer[256];
  2767. ANSI_STRING ansiText;
  2768. UNICODE_STRING unicodeText;
  2769. NTSTATUS ntStatus;
  2770. PAGED_CODE();
  2771. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceText\n"));
  2772. LOGENTRY('PQDT', DeviceObject, Irp, 0);
  2773. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2774. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2775. inquiryData = (PINQUIRYDATA)pdoDeviceExtension->InquiryDataBuffer;
  2776. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2777. textType = irpStack->Parameters.QueryDeviceText.DeviceTextType;
  2778. if (textType == DeviceTextDescription)
  2779. {
  2780. PUCHAR c;
  2781. LONG i;
  2782. RtlZeroMemory(ansiBuffer, sizeof(ansiBuffer));
  2783. RtlCopyMemory(ansiBuffer,
  2784. inquiryData->VendorId,
  2785. sizeof(inquiryData->VendorId));
  2786. c = ansiBuffer;
  2787. for (i = sizeof(inquiryData->VendorId)-1; i >= 0; i--)
  2788. {
  2789. if((c[i] != '\0') &&
  2790. (c[i] != ' '))
  2791. {
  2792. i++;
  2793. break;
  2794. }
  2795. }
  2796. c += i;
  2797. *c++ = ' ';
  2798. RtlCopyMemory(c,
  2799. inquiryData->ProductId,
  2800. sizeof(inquiryData->ProductId));
  2801. for (i = sizeof(inquiryData->ProductId)-1; i >= 0; i--)
  2802. {
  2803. if((c[i] != '\0') &&
  2804. (c[i] != ' '))
  2805. {
  2806. i++;
  2807. break;
  2808. }
  2809. }
  2810. c += i;
  2811. *c++ = ' ';
  2812. sprintf(c, "USB Device");
  2813. RtlInitAnsiString(&ansiText, ansiBuffer);
  2814. ntStatus = RtlAnsiStringToUnicodeString(&unicodeText,
  2815. &ansiText,
  2816. TRUE);
  2817. if (NT_SUCCESS(ntStatus))
  2818. {
  2819. Irp->IoStatus.Information = (ULONG_PTR)unicodeText.Buffer;
  2820. }
  2821. else
  2822. {
  2823. Irp->IoStatus.Information = (ULONG_PTR)NULL;
  2824. }
  2825. }
  2826. else
  2827. {
  2828. // If a device does not provide description or location information,
  2829. // the device's underlying bus driver completes the IRP without
  2830. // modifying Irp->IoStatus.Status or Ipr->IoStatus.Information.
  2831. //
  2832. ntStatus = Irp->IoStatus.Status;
  2833. }
  2834. Irp->IoStatus.Status = ntStatus;
  2835. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2836. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceText %08X\n", ntStatus));
  2837. LOGENTRY('pqdt', ntStatus, 0, 0);
  2838. return ntStatus;
  2839. }
  2840. //******************************************************************************
  2841. //
  2842. // USBSTOR_PdoBusQueryInstanceId()
  2843. //
  2844. // This routine handles IRP_MN_QUERY_ID BusQueryInstanceID for the PDO.
  2845. //
  2846. //******************************************************************************
  2847. NTSTATUS
  2848. USBSTOR_PdoBusQueryInstanceId (
  2849. IN PDEVICE_OBJECT DeviceObject,
  2850. OUT PUNICODE_STRING UnicodeString
  2851. )
  2852. {
  2853. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  2854. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  2855. USHORT length;
  2856. NTSTATUS ntStatus;
  2857. PAGED_CODE();
  2858. DBGPRINT(2, ("enter: USBSTOR_PdoBusQueryInstanceId\n"));
  2859. pdoDeviceExtension = DeviceObject->DeviceExtension;
  2860. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  2861. fdoDeviceExtension = pdoDeviceExtension->ParentFDO->DeviceExtension;
  2862. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  2863. if (fdoDeviceExtension->SerialNumber == NULL)
  2864. {
  2865. // If we set DEVICE_CAPABILITIES.UniqueID = 0 in response to a
  2866. // IRP_MN_QUERY_CAPABILITIES, we can return a NULL ID in response
  2867. // to a BusQueryInstanceID.
  2868. //
  2869. ntStatus = STATUS_SUCCESS;
  2870. }
  2871. else
  2872. {
  2873. // Return an NULL-terminated InstanceId string with the format:
  2874. // <USB Device SerialNumberString> + '&' + <LUN value in hex>
  2875. //
  2876. length = fdoDeviceExtension->SerialNumber->bLength -
  2877. sizeof(USB_COMMON_DESCRIPTOR) +
  2878. 3 * sizeof(WCHAR);
  2879. UnicodeString->Buffer = ExAllocatePoolWithTag(
  2880. PagedPool,
  2881. length,
  2882. POOL_TAG);
  2883. if (UnicodeString->Buffer == NULL)
  2884. {
  2885. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2886. }
  2887. else
  2888. {
  2889. UnicodeString->Length = length - sizeof(WCHAR);
  2890. UnicodeString->MaximumLength = length;
  2891. // Copy the USB Device SerialNumberString
  2892. //
  2893. RtlCopyMemory(UnicodeString->Buffer,
  2894. &fdoDeviceExtension->SerialNumber->bString[0],
  2895. length - 3 * sizeof(WCHAR));
  2896. // Append a '&'
  2897. //
  2898. UnicodeString->Buffer[length/sizeof(WCHAR) - 3] = (WCHAR)'&';
  2899. // Append the LUN value in hex
  2900. //
  2901. if (pdoDeviceExtension->LUN <= 9)
  2902. {
  2903. UnicodeString->Buffer[length/sizeof(WCHAR) - 2] =
  2904. (WCHAR)('0' + pdoDeviceExtension->LUN);
  2905. }
  2906. else
  2907. {
  2908. UnicodeString->Buffer[length/sizeof(WCHAR) - 2] =
  2909. (WCHAR)('A' + pdoDeviceExtension->LUN - 0xA);
  2910. }
  2911. UnicodeString->Buffer[length/sizeof(WCHAR) - 1] =
  2912. UNICODE_NULL;
  2913. ntStatus = STATUS_SUCCESS;
  2914. }
  2915. }
  2916. DBGPRINT(2, ("exit: USBSTOR_PdoBusQueryInstanceId %08X\n", ntStatus));
  2917. return ntStatus;
  2918. }
  2919. //******************************************************************************
  2920. //
  2921. // USBSTOR_PdoQueryDeviceRelations()
  2922. //
  2923. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_DEVICE_RELATIONS for the PDO.
  2924. //
  2925. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2926. // an arbitrary thread.
  2927. //
  2928. //******************************************************************************
  2929. NTSTATUS
  2930. USBSTOR_PdoQueryDeviceRelations (
  2931. IN PDEVICE_OBJECT DeviceObject,
  2932. IN PIRP Irp
  2933. )
  2934. {
  2935. PIO_STACK_LOCATION irpStack;
  2936. DEVICE_RELATION_TYPE relationType;
  2937. PDEVICE_RELATIONS newRelations;
  2938. NTSTATUS ntStatus;
  2939. PAGED_CODE();
  2940. irpStack = IoGetCurrentIrpStackLocation(Irp);
  2941. relationType = irpStack->Parameters.QueryDeviceRelations.Type;
  2942. DBGPRINT(2, ("enter: USBSTOR_PdoQueryDeviceRelations %d\n",
  2943. relationType));
  2944. LOGENTRY('PQDR', DeviceObject, Irp, relationType);
  2945. switch (relationType)
  2946. {
  2947. case TargetDeviceRelation:
  2948. //
  2949. // Return a relation list containing ourself.
  2950. //
  2951. newRelations = ExAllocatePoolWithTag(
  2952. PagedPool,
  2953. sizeof(DEVICE_RELATIONS),
  2954. POOL_TAG);
  2955. if (newRelations)
  2956. {
  2957. newRelations->Count = 1;
  2958. newRelations->Objects[0] = DeviceObject;
  2959. ObReferenceObject(DeviceObject);
  2960. ntStatus = STATUS_SUCCESS;
  2961. Irp->IoStatus.Status = ntStatus;
  2962. Irp->IoStatus.Information = (ULONG_PTR)newRelations;
  2963. }
  2964. else
  2965. {
  2966. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2967. Irp->IoStatus.Status = ntStatus;
  2968. Irp->IoStatus.Information = 0;
  2969. }
  2970. break;
  2971. case BusRelations:
  2972. case EjectionRelations:
  2973. case PowerRelations:
  2974. case RemovalRelations:
  2975. default:
  2976. //
  2977. // Just complete the request with it's current status
  2978. //
  2979. ntStatus = Irp->IoStatus.Status;
  2980. break;
  2981. }
  2982. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2983. DBGPRINT(2, ("exit: USBSTOR_PdoQueryDeviceRelations %08X\n", ntStatus));
  2984. LOGENTRY('pqdr', ntStatus, 0, 0);
  2985. return ntStatus;
  2986. }
  2987. //******************************************************************************
  2988. //
  2989. // USBSTOR_PdoQueryCapabilities()
  2990. //
  2991. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES for the PDO.
  2992. //
  2993. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  2994. // an arbitrary thread.
  2995. //
  2996. //******************************************************************************
  2997. NTSTATUS
  2998. USBSTOR_PdoQueryCapabilities (
  2999. IN PDEVICE_OBJECT DeviceObject,
  3000. IN PIRP Irp
  3001. )
  3002. {
  3003. PPDO_DEVICE_EXTENSION pdoDeviceExtension;
  3004. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3005. PIO_STACK_LOCATION irpStack;
  3006. PDEVICE_CAPABILITIES deviceCapabilities;
  3007. NTSTATUS ntStatus;
  3008. PAGED_CODE();
  3009. pdoDeviceExtension = DeviceObject->DeviceExtension;
  3010. ASSERT(pdoDeviceExtension->Type == USBSTOR_DO_TYPE_PDO);
  3011. fdoDeviceExtension = pdoDeviceExtension->ParentFDO->DeviceExtension;
  3012. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3013. DBGPRINT(2, ("enter: USBSTOR_PdoQueryCapabilities\n"));
  3014. LOGENTRY('PQCP', DeviceObject, Irp, 0);
  3015. irpStack = IoGetCurrentIrpStackLocation(Irp);
  3016. deviceCapabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  3017. // Pass IRP_MN_QUERY_CAPABILITIES Irp down the stack first before we do
  3018. // anything.
  3019. //
  3020. ntStatus = USBSTOR_SyncPassDownIrp(pdoDeviceExtension->ParentFDO,
  3021. Irp);
  3022. if (!NT_SUCCESS(ntStatus))
  3023. {
  3024. DBGPRINT(1, ("Lower driver failed IRP_MN_QUERY_CAPABILITIES\n"));
  3025. }
  3026. else
  3027. {
  3028. if (fdoDeviceExtension->SerialNumber == NULL)
  3029. {
  3030. deviceCapabilities->UniqueID = FALSE;
  3031. }
  3032. deviceCapabilities->Removable = FALSE;
  3033. }
  3034. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  3035. DBGPRINT(2, ("exit: USBSTOR_PdoQueryCapabilities %08X\n", ntStatus));
  3036. LOGENTRY('pqcp', ntStatus, 0, 0);
  3037. return ntStatus;
  3038. }
  3039. //******************************************************************************
  3040. //
  3041. // USBSTOR_SyncPassDownIrp()
  3042. //
  3043. //******************************************************************************
  3044. NTSTATUS
  3045. USBSTOR_SyncPassDownIrp (
  3046. IN PDEVICE_OBJECT DeviceObject,
  3047. IN PIRP Irp
  3048. )
  3049. {
  3050. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3051. NTSTATUS ntStatus;
  3052. KEVENT localevent;
  3053. PAGED_CODE();
  3054. DBGPRINT(2, ("enter: USBSTOR_SyncPassDownIrp\n"));
  3055. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3056. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3057. // Initialize the event we'll wait on
  3058. //
  3059. KeInitializeEvent(&localevent,
  3060. SynchronizationEvent,
  3061. FALSE);
  3062. // Copy down Irp params for the next driver
  3063. //
  3064. IoCopyCurrentIrpStackLocationToNext(Irp);
  3065. // Set the completion routine, which will signal the event
  3066. //
  3067. IoSetCompletionRoutine(Irp,
  3068. USBSTOR_SyncCompletionRoutine,
  3069. &localevent,
  3070. TRUE, // InvokeOnSuccess
  3071. TRUE, // InvokeOnError
  3072. TRUE); // InvokeOnCancel
  3073. // Pass the Irp down the stack
  3074. //
  3075. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3076. Irp);
  3077. // If the request is pending, block until it completes
  3078. //
  3079. if (ntStatus == STATUS_PENDING)
  3080. {
  3081. KeWaitForSingleObject(&localevent,
  3082. Executive,
  3083. KernelMode,
  3084. FALSE,
  3085. NULL);
  3086. ntStatus = Irp->IoStatus.Status;
  3087. }
  3088. DBGPRINT(2, ("exit: USBSTOR_SyncPassDownIrp %08X\n", ntStatus));
  3089. return ntStatus;
  3090. }
  3091. //******************************************************************************
  3092. //
  3093. // USBSTOR_SyncCompletionRoutine()
  3094. //
  3095. // Completion routine used by USBSTOR_SyncPassDownIrp and
  3096. // USBSTOR_SyncSendUsbRequest
  3097. //
  3098. // If the Irp is one we allocated ourself, DeviceObject is NULL.
  3099. //
  3100. //******************************************************************************
  3101. NTSTATUS
  3102. USBSTOR_SyncCompletionRoutine (
  3103. IN PDEVICE_OBJECT DeviceObject,
  3104. IN PIRP Irp,
  3105. IN PVOID Context
  3106. )
  3107. {
  3108. PKEVENT kevent;
  3109. LOGENTRY('SCR ', DeviceObject, Irp, Irp->IoStatus.Status);
  3110. kevent = (PKEVENT)Context;
  3111. KeSetEvent(kevent,
  3112. IO_NO_INCREMENT,
  3113. FALSE);
  3114. return STATUS_MORE_PROCESSING_REQUIRED;
  3115. }
  3116. //******************************************************************************
  3117. //
  3118. // USBSTOR_SyncSendUsbRequest()
  3119. //
  3120. // Must be called at IRQL PASSIVE_LEVEL
  3121. //
  3122. //******************************************************************************
  3123. NTSTATUS
  3124. USBSTOR_SyncSendUsbRequest (
  3125. IN PDEVICE_OBJECT DeviceObject,
  3126. IN PURB Urb
  3127. )
  3128. {
  3129. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3130. KEVENT localevent;
  3131. PIRP irp;
  3132. PIO_STACK_LOCATION nextStack;
  3133. NTSTATUS ntStatus;
  3134. PAGED_CODE();
  3135. DBGPRINT(3, ("enter: USBSTOR_SyncSendUsbRequest\n"));
  3136. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3137. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3138. // Initialize the event we'll wait on
  3139. //
  3140. KeInitializeEvent(&localevent,
  3141. SynchronizationEvent,
  3142. FALSE);
  3143. // Allocate the Irp
  3144. //
  3145. irp = IoAllocateIrp(fdoDeviceExtension->StackDeviceObject->StackSize, FALSE);
  3146. LOGENTRY('SSUR', DeviceObject, irp, Urb);
  3147. if (irp == NULL)
  3148. {
  3149. return STATUS_INSUFFICIENT_RESOURCES;
  3150. }
  3151. // Set the Irp parameters
  3152. //
  3153. nextStack = IoGetNextIrpStackLocation(irp);
  3154. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  3155. nextStack->Parameters.DeviceIoControl.IoControlCode =
  3156. IOCTL_INTERNAL_USB_SUBMIT_URB;
  3157. nextStack->Parameters.Others.Argument1 = Urb;
  3158. // Set the completion routine, which will signal the event
  3159. //
  3160. IoSetCompletionRoutine(irp,
  3161. USBSTOR_SyncCompletionRoutine,
  3162. &localevent,
  3163. TRUE, // InvokeOnSuccess
  3164. TRUE, // InvokeOnError
  3165. TRUE); // InvokeOnCancel
  3166. // Pass the Irp & Urb down the stack
  3167. //
  3168. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3169. irp);
  3170. // If the request is pending, block until it completes
  3171. //
  3172. if (ntStatus == STATUS_PENDING)
  3173. {
  3174. LARGE_INTEGER timeout;
  3175. // Specify a timeout of 5 seconds to wait for this call to complete.
  3176. //
  3177. timeout.QuadPart = -10000 * 5000;
  3178. ntStatus = KeWaitForSingleObject(&localevent,
  3179. Executive,
  3180. KernelMode,
  3181. FALSE,
  3182. &timeout);
  3183. if (ntStatus == STATUS_TIMEOUT)
  3184. {
  3185. ntStatus = STATUS_IO_TIMEOUT;
  3186. // Cancel the Irp we just sent.
  3187. //
  3188. IoCancelIrp(irp);
  3189. // And wait until the cancel completes
  3190. //
  3191. KeWaitForSingleObject(&localevent,
  3192. Executive,
  3193. KernelMode,
  3194. FALSE,
  3195. NULL);
  3196. }
  3197. else
  3198. {
  3199. ntStatus = irp->IoStatus.Status;
  3200. }
  3201. }
  3202. // Done with the Irp, now free it.
  3203. //
  3204. IoFreeIrp(irp);
  3205. LOGENTRY('ssur', ntStatus, Urb, Urb->UrbHeader.Status);
  3206. DBGPRINT(3, ("exit: USBSTOR_SyncSendUsbRequest %08X\n", ntStatus));
  3207. return ntStatus;
  3208. }
  3209. //******************************************************************************
  3210. //
  3211. // USBSTOR_GetDescriptor()
  3212. //
  3213. // Must be called at IRQL PASSIVE_LEVEL
  3214. //
  3215. //******************************************************************************
  3216. NTSTATUS
  3217. USBSTOR_GetDescriptor (
  3218. IN PDEVICE_OBJECT DeviceObject,
  3219. IN UCHAR Recipient,
  3220. IN UCHAR DescriptorType,
  3221. IN UCHAR Index,
  3222. IN USHORT LanguageId,
  3223. IN ULONG RetryCount,
  3224. IN ULONG DescriptorLength,
  3225. OUT PUCHAR *Descriptor
  3226. )
  3227. {
  3228. USHORT function;
  3229. PURB urb;
  3230. NTSTATUS ntStatus;
  3231. PAGED_CODE();
  3232. DBGPRINT(2, ("enter: USBSTOR_GetDescriptor\n"));
  3233. *Descriptor = NULL;
  3234. // Set the URB function based on Recipient {Device, Interface, Endpoint}
  3235. //
  3236. switch (Recipient)
  3237. {
  3238. case USB_RECIPIENT_DEVICE:
  3239. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
  3240. break;
  3241. case USB_RECIPIENT_INTERFACE:
  3242. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
  3243. break;
  3244. case USB_RECIPIENT_ENDPOINT:
  3245. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
  3246. break;
  3247. default:
  3248. return STATUS_INVALID_PARAMETER;
  3249. }
  3250. // Allocate a descriptor buffer
  3251. //
  3252. *Descriptor = ExAllocatePoolWithTag(NonPagedPool,
  3253. DescriptorLength,
  3254. POOL_TAG);
  3255. if (*Descriptor != NULL)
  3256. {
  3257. // Allocate a URB for the Get Descriptor request
  3258. //
  3259. urb = ExAllocatePoolWithTag(NonPagedPool,
  3260. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  3261. POOL_TAG);
  3262. if (urb != NULL)
  3263. {
  3264. do
  3265. {
  3266. // Initialize the URB
  3267. //
  3268. urb->UrbHeader.Function = function;
  3269. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  3270. urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
  3271. urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
  3272. urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
  3273. urb->UrbControlDescriptorRequest.UrbLink = NULL;
  3274. urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
  3275. urb->UrbControlDescriptorRequest.Index = Index;
  3276. urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
  3277. // Send the URB down the stack
  3278. //
  3279. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3280. urb);
  3281. if (NT_SUCCESS(ntStatus))
  3282. {
  3283. // No error, make sure the length and type are correct
  3284. //
  3285. if ((DescriptorLength ==
  3286. urb->UrbControlDescriptorRequest.TransferBufferLength) &&
  3287. (DescriptorType ==
  3288. ((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
  3289. {
  3290. // The length and type are correct, all done
  3291. //
  3292. break;
  3293. }
  3294. else
  3295. {
  3296. // No error, but the length or type is incorrect
  3297. //
  3298. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3299. }
  3300. }
  3301. } while (RetryCount-- > 0);
  3302. ExFreePool(urb);
  3303. }
  3304. else
  3305. {
  3306. // Failed to allocate the URB
  3307. //
  3308. ExFreePool(*Descriptor);
  3309. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3310. }
  3311. }
  3312. else
  3313. {
  3314. // Failed to allocate the descriptor buffer
  3315. //
  3316. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3317. }
  3318. if (!NT_SUCCESS(ntStatus))
  3319. {
  3320. if (*Descriptor != NULL)
  3321. {
  3322. ExFreePool(*Descriptor);
  3323. *Descriptor = NULL;
  3324. }
  3325. }
  3326. DBGPRINT(2, ("exit: USBSTOR_GetDescriptor %08X\n", ntStatus));
  3327. return ntStatus;
  3328. }
  3329. //******************************************************************************
  3330. //
  3331. // USBSTOR_GetMaxLun()
  3332. //
  3333. // Must be called at IRQL PASSIVE_LEVEL
  3334. //
  3335. //******************************************************************************
  3336. NTSTATUS
  3337. USBSTOR_GetMaxLun (
  3338. IN PDEVICE_OBJECT DeviceObject,
  3339. OUT PUCHAR MaxLun
  3340. )
  3341. {
  3342. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3343. PUCHAR maxLunBuf;
  3344. ULONG retryCount;
  3345. PURB urb;
  3346. NTSTATUS ntStatus;
  3347. PAGED_CODE();
  3348. DBGPRINT(2, ("enter: USBSTOR_GetMaxLun\n"));
  3349. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3350. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3351. // Return zero unless we successfully return a non-zero value
  3352. //
  3353. *MaxLun = 0;
  3354. // Allocate a URB for the Get Max LUN request, plus an extra byte at
  3355. // the end for the transfer buffer.
  3356. //
  3357. urb = ExAllocatePoolWithTag(NonPagedPool,
  3358. sizeof(URB) + 1,
  3359. POOL_TAG);
  3360. if (urb != NULL)
  3361. {
  3362. // Get a pointer to the transfer buffer, which is the byte immediately
  3363. // after the end of the URB.
  3364. //
  3365. maxLunBuf = (PUCHAR)(urb + 1);
  3366. retryCount = 2;
  3367. do
  3368. {
  3369. // Initialize the Control Transfer URB, all fields default to zero
  3370. //
  3371. RtlZeroMemory(urb, sizeof(URB) + 1);
  3372. CLASS_URB(urb).Hdr.Length = sizeof(CLASS_URB(urb));
  3373. CLASS_URB(urb).Hdr.Function = URB_FUNCTION_CLASS_INTERFACE;
  3374. CLASS_URB(urb).TransferFlags = USBD_TRANSFER_DIRECTION_IN;
  3375. CLASS_URB(urb).TransferBufferLength = 1;
  3376. CLASS_URB(urb).TransferBuffer = maxLunBuf;
  3377. // CLASS_URB(urb).TransferBufferMDL is already zero
  3378. // CLASS_URB(urb).RequestTypeReservedBits is already zero
  3379. CLASS_URB(urb).Request = BULK_ONLY_GET_MAX_LUN;
  3380. // CLASS_URB(urb).Value is already zero
  3381. // Target the request at the proper interface on the device
  3382. //
  3383. CLASS_URB(urb).Index = fdoDeviceExtension->InterfaceInfo->InterfaceNumber;
  3384. // Send the URB down the stack
  3385. //
  3386. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3387. urb);
  3388. if (NT_SUCCESS(ntStatus))
  3389. {
  3390. // No error, make sure the length is correct
  3391. //
  3392. if (CLASS_URB(urb).TransferBufferLength == 1)
  3393. {
  3394. // The length is correct, return the value if it looks ok
  3395. //
  3396. if (*maxLunBuf <= BULK_ONLY_MAXIMUM_LUN)
  3397. {
  3398. *MaxLun = *maxLunBuf;
  3399. }
  3400. else
  3401. {
  3402. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3403. }
  3404. break;
  3405. }
  3406. else
  3407. {
  3408. // No error, but the length or type is incorrect
  3409. //
  3410. ntStatus = STATUS_DEVICE_DATA_ERROR;
  3411. }
  3412. }
  3413. else if (USBD_STATUS(CLASS_URB(urb).Hdr.Status) ==
  3414. USBD_STATUS(USBD_STATUS_STALL_PID))
  3415. {
  3416. // Some devices which do not support the Get Max LUN request
  3417. // get confused and will STALL a CBW on the Bulk endpoint
  3418. // it if immediately follows the Get Max LUN request.
  3419. //
  3420. // It should never be necessary to send a Clear_Feature
  3421. // Endpoint_Stall for Control EP0, but doing so appears to
  3422. // be one way to unconfuse devices which are confused by the
  3423. // Get Max LUN request.
  3424. // Initialize the Control Transfer URB, all fields default to zero
  3425. //
  3426. RtlZeroMemory(urb, sizeof(URB));
  3427. FEATURE_URB(urb).Hdr.Length = sizeof(FEATURE_URB(urb));
  3428. FEATURE_URB(urb).Hdr.Function = URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT;
  3429. FEATURE_URB(urb).FeatureSelector = USB_FEATURE_ENDPOINT_STALL;
  3430. // FEATURE_URB(urb).Index is already zero
  3431. // Send the URB down the stack
  3432. //
  3433. USBSTOR_SyncSendUsbRequest(DeviceObject,
  3434. urb);
  3435. }
  3436. } while (retryCount-- > 0);
  3437. ExFreePool(urb);
  3438. }
  3439. else
  3440. {
  3441. // Failed to allocate the URB
  3442. //
  3443. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3444. }
  3445. DBGPRINT(2, ("exit: USBSTOR_GetMaxLun %08X\n", ntStatus));
  3446. return ntStatus;
  3447. }
  3448. //******************************************************************************
  3449. //
  3450. // USBSTOR_SelectConfiguration()
  3451. //
  3452. // Must be called at IRQL PASSIVE_LEVEL
  3453. //
  3454. //******************************************************************************
  3455. NTSTATUS
  3456. USBSTOR_SelectConfiguration (
  3457. IN PDEVICE_OBJECT DeviceObject
  3458. )
  3459. {
  3460. PURB urb;
  3461. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3462. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  3463. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  3464. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  3465. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  3466. LONG i;
  3467. LONG bulkInIndex;
  3468. LONG bulkOutIndex;
  3469. LONG interruptInIndex;
  3470. NTSTATUS ntStatus;
  3471. PAGED_CODE();
  3472. DBGPRINT(2, ("enter: USBSTOR_SelectConfiguration\n"));
  3473. LOGENTRY('SCON', DeviceObject, 0, 0);
  3474. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3475. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3476. configurationDescriptor = fdoDeviceExtension->ConfigurationDescriptor;
  3477. // Allocate storage for an Inteface List to use as an input/output
  3478. // parameter to USBD_CreateConfigurationRequestEx().
  3479. //
  3480. interfaceList = ExAllocatePoolWithTag(
  3481. PagedPool,
  3482. sizeof(USBD_INTERFACE_LIST_ENTRY) * 2,
  3483. POOL_TAG);
  3484. if (interfaceList)
  3485. {
  3486. // Mutate configuration descriptor to suit our wishes
  3487. //
  3488. USBSTOR_AdjustConfigurationDescriptor(
  3489. DeviceObject,
  3490. fdoDeviceExtension->ConfigurationDescriptor,
  3491. &interfaceDescriptor,
  3492. &bulkInIndex,
  3493. &bulkOutIndex,
  3494. &interruptInIndex);
  3495. // Save the Interface Descriptor pointer so we don't have
  3496. // to parse the Configuration Descriptor again in case we
  3497. // want to look at it.
  3498. //
  3499. fdoDeviceExtension->InterfaceDescriptor = interfaceDescriptor;
  3500. if (interfaceDescriptor)
  3501. {
  3502. // Add the single Interface Descriptor we care about to the
  3503. // interface list, then terminate the list.
  3504. //
  3505. interfaceList[0].InterfaceDescriptor = interfaceDescriptor;
  3506. interfaceList[1].InterfaceDescriptor = NULL;
  3507. // USBD will fail a SELECT_CONFIGURATION request if the Config
  3508. // Descriptor bNumInterfaces does not match the number of interfaces
  3509. // in the SELECT_CONFIGURATION request. Since we are ignoring
  3510. // any interfaces other than the first interface, set the Config
  3511. // Descriptor bNumInterfaces to 1.
  3512. //
  3513. // This is only necessary in case this driver is loaded for an
  3514. // entire multiple interface device and not as a single interface
  3515. // child of the composite parent driver.
  3516. //
  3517. configurationDescriptor->bNumInterfaces = 1;
  3518. // Create a SELECT_CONFIGURATION URB, turning the Interface
  3519. // Descriptors in the interfaceList into USBD_INTERFACE_INFORMATION
  3520. // structures in the URB.
  3521. //
  3522. urb = USBD_CreateConfigurationRequestEx(
  3523. configurationDescriptor,
  3524. interfaceList
  3525. );
  3526. if (urb)
  3527. {
  3528. // Now issue the USB request to set the Configuration
  3529. //
  3530. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3531. urb);
  3532. if (NT_SUCCESS(ntStatus))
  3533. {
  3534. // Save the configuration handle for this device in
  3535. // the Device Extension.
  3536. //
  3537. fdoDeviceExtension->ConfigurationHandle =
  3538. urb->UrbSelectConfiguration.ConfigurationHandle;
  3539. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  3540. // Save a copy of the interface information returned
  3541. // by the SELECT_CONFIGURATION request in the Device
  3542. // Extension. This gives us a list of PIPE_INFORMATION
  3543. // structures for each pipe opened in this configuration.
  3544. //
  3545. ASSERT(fdoDeviceExtension->InterfaceInfo == NULL);
  3546. fdoDeviceExtension->InterfaceInfo =
  3547. ExAllocatePoolWithTag(NonPagedPool,
  3548. interfaceInfo->Length,
  3549. POOL_TAG);
  3550. if (fdoDeviceExtension->InterfaceInfo)
  3551. {
  3552. RtlCopyMemory(fdoDeviceExtension->InterfaceInfo,
  3553. interfaceInfo,
  3554. interfaceInfo->Length);
  3555. }
  3556. else
  3557. {
  3558. // Could not allocate a copy of interface information
  3559. //
  3560. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3561. }
  3562. }
  3563. if (NT_SUCCESS(ntStatus))
  3564. {
  3565. // Reuse the SELECT_CONFIGURATION request URB as a
  3566. // SELECT_INTERFACE request URB and send down a request to
  3567. // select the default alternate interface setting that is
  3568. // currently in effect. The point of this seemingly
  3569. // useless request is to make sure the endpoint
  3570. // MaximumTransferSize values are in effect.
  3571. //
  3572. // When USBHUB is loaded as a composite parent for a
  3573. // multiple interface device it ignores SELECT_CONFIGURATION
  3574. // requests from child device drivers. In particular the
  3575. // MaximumTransferSize values of child driver SELECT_CONFIGURATION
  3576. // requests are ignored and the default 4KB value remains
  3577. // in effect. The composite parent driver will respect the
  3578. // MaximumTransferSize values of child driver SELECT_INTERFACE
  3579. // requests.
  3580. //
  3581. ASSERT(GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes) <
  3582. GET_SELECT_CONFIGURATION_REQUEST_SIZE(1, fdoDeviceExtension->InterfaceInfo->NumberOfPipes));
  3583. RtlZeroMemory(urb, GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes));
  3584. urb->UrbSelectInterface.Hdr.Length =
  3585. (USHORT)GET_SELECT_INTERFACE_REQUEST_SIZE(fdoDeviceExtension->InterfaceInfo->NumberOfPipes);
  3586. urb->UrbSelectInterface.Hdr.Function =
  3587. URB_FUNCTION_SELECT_INTERFACE;
  3588. urb->UrbSelectInterface.ConfigurationHandle =
  3589. fdoDeviceExtension->ConfigurationHandle;
  3590. interfaceInfo = &urb->UrbSelectInterface.Interface;
  3591. RtlCopyMemory(interfaceInfo,
  3592. fdoDeviceExtension->InterfaceInfo,
  3593. fdoDeviceExtension->InterfaceInfo->Length);
  3594. // Override the USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE
  3595. // for all pipes.
  3596. //
  3597. for (i=0; i<(LONG)interfaceInfo->NumberOfPipes; i++)
  3598. {
  3599. if (i == bulkInIndex || i == bulkOutIndex)
  3600. {
  3601. interfaceInfo->Pipes[i].MaximumTransferSize =
  3602. USBSTOR_MAX_TRANSFER_SIZE;
  3603. DBGPRINT(1, ("Set pipe %d MaximumTransferSize to %X\n",
  3604. i,
  3605. interfaceInfo->Pipes[i].MaximumTransferSize));
  3606. }
  3607. else if (i == interruptInIndex)
  3608. {
  3609. interfaceInfo->Pipes[i].MaximumTransferSize =
  3610. sizeof(USHORT);
  3611. DBGPRINT(1, ("Set pipe %d MaximumTransferSize to %X\n",
  3612. i,
  3613. interfaceInfo->Pipes[i].MaximumTransferSize));
  3614. }
  3615. }
  3616. // Now issue the USB request to set the Interface
  3617. //
  3618. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3619. urb);
  3620. if (NT_SUCCESS(ntStatus))
  3621. {
  3622. ASSERT(interfaceInfo->Length ==
  3623. fdoDeviceExtension->InterfaceInfo->Length);
  3624. RtlCopyMemory(fdoDeviceExtension->InterfaceInfo,
  3625. interfaceInfo,
  3626. fdoDeviceExtension->InterfaceInfo->Length);
  3627. }
  3628. }
  3629. // Done with the URB
  3630. //
  3631. ExFreePool(urb);
  3632. }
  3633. else
  3634. {
  3635. // Could not allocate urb
  3636. //
  3637. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3638. }
  3639. }
  3640. else
  3641. {
  3642. // Did not parse an Interface Descriptor out of the Configuration
  3643. // Descriptor, the Configuration Descriptor must be bad.
  3644. //
  3645. ntStatus = STATUS_UNSUCCESSFUL;
  3646. }
  3647. // Done with the interface list
  3648. //
  3649. ExFreePool(interfaceList);
  3650. }
  3651. else
  3652. {
  3653. // Could not allocate Interface List
  3654. //
  3655. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3656. }
  3657. DBGPRINT(2, ("exit: USBSTOR_SelectConfiguration %08X\n", ntStatus));
  3658. LOGENTRY('scon', ntStatus, 0, 0);
  3659. return ntStatus;
  3660. }
  3661. //******************************************************************************
  3662. //
  3663. // USBSTOR_UnConfigure()
  3664. //
  3665. // Must be called at IRQL PASSIVE_LEVEL
  3666. //
  3667. //******************************************************************************
  3668. NTSTATUS
  3669. USBSTOR_UnConfigure (
  3670. IN PDEVICE_OBJECT DeviceObject
  3671. )
  3672. {
  3673. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3674. NTSTATUS ntStatus;
  3675. PURB urb;
  3676. ULONG ulSize;
  3677. PAGED_CODE();
  3678. DBGPRINT(2, ("enter: USBSTOR_UnConfigure\n"));
  3679. LOGENTRY('UCON', DeviceObject, 0, 0);
  3680. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3681. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3682. // Allocate a URB for the SELECT_CONFIGURATION request. As we are
  3683. // unconfiguring the device, the request needs no pipe and interface
  3684. // information structures.
  3685. //
  3686. ulSize = sizeof(struct _URB_SELECT_CONFIGURATION) -
  3687. sizeof(USBD_INTERFACE_INFORMATION);
  3688. urb = ExAllocatePoolWithTag(NonPagedPool, ulSize, POOL_TAG);
  3689. if (urb)
  3690. {
  3691. // Initialize the URB. A NULL Configuration Descriptor indicates
  3692. // that the device should be unconfigured.
  3693. //
  3694. UsbBuildSelectConfigurationRequest(urb,
  3695. (USHORT)ulSize,
  3696. NULL);
  3697. // Now issue the USB request to set the Configuration
  3698. //
  3699. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject,
  3700. urb);
  3701. // Done with the URB now.
  3702. //
  3703. ExFreePool(urb);
  3704. fdoDeviceExtension->ConfigurationHandle = 0;
  3705. // Free the copy of the interface information that was allocated in
  3706. // USBSTOR_SelectConfiguration().
  3707. //
  3708. if (fdoDeviceExtension->InterfaceInfo != NULL)
  3709. {
  3710. ExFreePool(fdoDeviceExtension->InterfaceInfo);
  3711. fdoDeviceExtension->InterfaceInfo = NULL;
  3712. }
  3713. }
  3714. else
  3715. {
  3716. // Could not allocate the URB.
  3717. //
  3718. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3719. }
  3720. DBGPRINT(2, ("exit: USBSTOR_UnConfigure %08X\n", ntStatus));
  3721. LOGENTRY('ucon', ntStatus, 0, 0);
  3722. return ntStatus;
  3723. }
  3724. //******************************************************************************
  3725. //
  3726. // USBSTOR_ResetPipe()
  3727. //
  3728. // This will reset the host pipe to Data0 and should also reset the device
  3729. // endpoint to Data0 for Bulk and Interrupt pipes by issuing a Clear_Feature
  3730. // Endpoint_Stall to the device endpoint.
  3731. //
  3732. // Must be called at IRQL PASSIVE_LEVEL
  3733. //
  3734. //******************************************************************************
  3735. NTSTATUS
  3736. USBSTOR_ResetPipe (
  3737. IN PDEVICE_OBJECT DeviceObject,
  3738. IN USBD_PIPE_HANDLE Pipe
  3739. )
  3740. {
  3741. PURB urb;
  3742. NTSTATUS ntStatus;
  3743. PAGED_CODE();
  3744. DBGPRINT(2, ("enter: USBSTOR_ResetPipe\n"));
  3745. LOGENTRY('RESP', DeviceObject, Pipe, 0);
  3746. // Allocate URB for RESET_PIPE request
  3747. //
  3748. urb = ExAllocatePoolWithTag(NonPagedPool,
  3749. sizeof(struct _URB_PIPE_REQUEST),
  3750. POOL_TAG);
  3751. if (urb != NULL)
  3752. {
  3753. // Initialize RESET_PIPE request URB
  3754. //
  3755. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  3756. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  3757. urb->UrbPipeRequest.PipeHandle = Pipe;
  3758. // Submit RESET_PIPE request URB
  3759. //
  3760. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject, urb);
  3761. // Done with URB for RESET_PIPE request, free it
  3762. //
  3763. ExFreePool(urb);
  3764. }
  3765. else
  3766. {
  3767. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3768. }
  3769. DBGPRINT(2, ("exit: USBSTOR_ResetPipe %08X\n", ntStatus));
  3770. LOGENTRY('resp', ntStatus, 0, 0);
  3771. return ntStatus;
  3772. }
  3773. //******************************************************************************
  3774. //
  3775. // USBSTOR_AbortPipe()
  3776. //
  3777. // Must be called at IRQL PASSIVE_LEVEL
  3778. //
  3779. //******************************************************************************
  3780. NTSTATUS
  3781. USBSTOR_AbortPipe (
  3782. IN PDEVICE_OBJECT DeviceObject,
  3783. IN USBD_PIPE_HANDLE Pipe
  3784. )
  3785. {
  3786. PURB urb;
  3787. NTSTATUS ntStatus;
  3788. PAGED_CODE();
  3789. DBGPRINT(2, ("enter: USBSTOR_AbortPipe\n"));
  3790. LOGENTRY('ABRT', DeviceObject, Pipe, 0);
  3791. // Allocate URB for ABORT_PIPE request
  3792. //
  3793. urb = ExAllocatePoolWithTag(NonPagedPool,
  3794. sizeof(struct _URB_PIPE_REQUEST),
  3795. POOL_TAG);
  3796. if (urb != NULL)
  3797. {
  3798. // Initialize ABORT_PIPE request URB
  3799. //
  3800. urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  3801. urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  3802. urb->UrbPipeRequest.PipeHandle = Pipe;
  3803. // Submit ABORT_PIPE request URB
  3804. //
  3805. ntStatus = USBSTOR_SyncSendUsbRequest(DeviceObject, urb);
  3806. // Done with URB for ABORT_PIPE request, free it
  3807. //
  3808. ExFreePool(urb);
  3809. }
  3810. else
  3811. {
  3812. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3813. }
  3814. DBGPRINT(2, ("exit: USBSTOR_AbortPipe %08X\n", ntStatus));
  3815. LOGENTRY('abrt', ntStatus, 0, 0);
  3816. return ntStatus;
  3817. }
  3818. //******************************************************************************
  3819. //
  3820. // USBSTOR_GetBusInterface()
  3821. //
  3822. // Must be called at IRQL PASSIVE_LEVEL
  3823. //
  3824. //******************************************************************************
  3825. NTSTATUS
  3826. USBSTOR_GetBusInterface (
  3827. IN PDEVICE_OBJECT DeviceObject,
  3828. IN PUSB_BUS_INTERFACE_USBDI_V1 BusInterface
  3829. )
  3830. {
  3831. PFDO_DEVICE_EXTENSION fdoDeviceExtension;
  3832. PIRP irp;
  3833. KEVENT localevent;
  3834. PIO_STACK_LOCATION nextStack;
  3835. NTSTATUS ntStatus;
  3836. PAGED_CODE();
  3837. DBGPRINT(1, ("enter: USBSTOR_GetBusInterface\n"));
  3838. fdoDeviceExtension = DeviceObject->DeviceExtension;
  3839. ASSERT(fdoDeviceExtension->Type == USBSTOR_DO_TYPE_FDO);
  3840. RtlZeroMemory(BusInterface, sizeof(*BusInterface));
  3841. // Allocate the Irp
  3842. //
  3843. irp = IoAllocateIrp((CCHAR)(fdoDeviceExtension->StackDeviceObject->StackSize),
  3844. FALSE);
  3845. if (irp == NULL)
  3846. {
  3847. return STATUS_INSUFFICIENT_RESOURCES;
  3848. }
  3849. // Initialize the event we'll wait on.
  3850. //
  3851. KeInitializeEvent(&localevent,
  3852. SynchronizationEvent,
  3853. FALSE);
  3854. // Set the Irp parameters
  3855. //
  3856. nextStack = IoGetNextIrpStackLocation(irp);
  3857. nextStack->MajorFunction = IRP_MJ_PNP;
  3858. nextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  3859. nextStack->Parameters.DeviceIoControl.IoControlCode =
  3860. IOCTL_INTERNAL_USB_GET_PORT_STATUS;
  3861. nextStack->Parameters.QueryInterface.Interface =
  3862. (PINTERFACE)BusInterface;
  3863. nextStack->Parameters.QueryInterface.InterfaceSpecificData =
  3864. NULL;
  3865. nextStack->Parameters.QueryInterface.InterfaceType =
  3866. &USB_BUS_INTERFACE_USBDI_GUID;
  3867. nextStack->Parameters.QueryInterface.Size =
  3868. sizeof(*BusInterface);
  3869. nextStack->Parameters.QueryInterface.Version =
  3870. USB_BUSIF_USBDI_VERSION_1;
  3871. // Set the completion routine, which will signal the event
  3872. //
  3873. IoSetCompletionRoutineEx(DeviceObject,
  3874. irp,
  3875. USBSTOR_SyncCompletionRoutine,
  3876. &localevent,
  3877. TRUE, // InvokeOnSuccess
  3878. TRUE, // InvokeOnError
  3879. TRUE); // InvokeOnCancel
  3880. // All PnP IRP's need the Status field initialized to STATUS_NOT_SUPPORTED
  3881. //
  3882. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  3883. // Pass the Irp down the stack
  3884. //
  3885. ntStatus = IoCallDriver(fdoDeviceExtension->StackDeviceObject,
  3886. irp);
  3887. // If the request is pending, block until it completes
  3888. //
  3889. if (ntStatus == STATUS_PENDING)
  3890. {
  3891. KeWaitForSingleObject(&localevent,
  3892. Executive,
  3893. KernelMode,
  3894. FALSE,
  3895. NULL);
  3896. ntStatus = irp->IoStatus.Status;
  3897. }
  3898. IoFreeIrp(irp);
  3899. if (NT_SUCCESS(ntStatus))
  3900. {
  3901. ASSERT(BusInterface->Version == USB_BUSIF_USBDI_VERSION_1);
  3902. ASSERT(BusInterface->Size == sizeof(*BusInterface));
  3903. }
  3904. DBGPRINT(1, ("exit: USBSTOR_GetBusInterface %08X\n", ntStatus));
  3905. return ntStatus;
  3906. }