Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1971 lines
59 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. I82930.C
  5. Abstract:
  6. This source file contains the DriverEntry() and AddDevice() entry points
  7. for the I82930 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 <wdm.h>
  20. #include <usbdi.h>
  21. #include <usbdlib.h>
  22. #include <initguid.h>
  23. #include "i82930.h"
  24. #include "ioctl.h"
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text(PAGE, DriverEntry)
  27. #pragma alloc_text(PAGE, I82930_Unload)
  28. #pragma alloc_text(PAGE, I82930_AddDevice)
  29. #pragma alloc_text(PAGE, I82930_Power)
  30. #pragma alloc_text(PAGE, I82930_SystemControl)
  31. #pragma alloc_text(PAGE, I82930_Pnp)
  32. #pragma alloc_text(PAGE, I82930_StartDevice)
  33. #pragma alloc_text(PAGE, I82930_StopDevice)
  34. #pragma alloc_text(PAGE, I82930_RemoveDevice)
  35. #pragma alloc_text(PAGE, I82930_QueryStopRemoveDevice)
  36. #pragma alloc_text(PAGE, I82930_CancelStopRemoveDevice)
  37. #pragma alloc_text(PAGE, I82930_QueryCapabilities)
  38. #pragma alloc_text(PAGE, I82930_SyncPassDownIrp)
  39. #pragma alloc_text(PAGE, I82930_SyncSendUsbRequest)
  40. #pragma alloc_text(PAGE, I82930_GetDescriptor)
  41. #pragma alloc_text(PAGE, I82930_SelectConfiguration)
  42. #pragma alloc_text(PAGE, I82930_UnConfigure)
  43. #endif
  44. //******************************************************************************
  45. //
  46. // DriverEntry()
  47. //
  48. //******************************************************************************
  49. NTSTATUS
  50. DriverEntry (
  51. IN PDRIVER_OBJECT DriverObject,
  52. IN PUNICODE_STRING RegistryPath
  53. )
  54. {
  55. #if DBG
  56. // Query the registry for global parameters
  57. //
  58. I82930_QueryGlobalParams();
  59. #endif
  60. DBGPRINT(2, ("enter: DriverEntry\n"));
  61. DBGFBRK(DBGF_BRK_DRIVERENTRY);
  62. LOGINIT();
  63. //
  64. // Initialize the Driver Object with the driver's entry points
  65. //
  66. //
  67. // I82930.C
  68. //
  69. DriverObject->DriverUnload = I82930_Unload;
  70. DriverObject->DriverExtension->AddDevice = I82930_AddDevice;
  71. //
  72. // OCRW.C
  73. //
  74. DriverObject->MajorFunction[IRP_MJ_CREATE] = I82930_Create;
  75. DriverObject->MajorFunction[IRP_MJ_CLOSE] = I82930_Close;
  76. DriverObject->MajorFunction[IRP_MJ_READ] = I82930_ReadWrite;
  77. DriverObject->MajorFunction[IRP_MJ_WRITE] = I82930_ReadWrite;
  78. //
  79. // IOCTL.C
  80. //
  81. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = I82930_DeviceControl;
  82. //
  83. // I82930.C
  84. //
  85. DriverObject->MajorFunction[IRP_MJ_POWER] = I82930_Power;
  86. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = I82930_SystemControl;
  87. DriverObject->MajorFunction[IRP_MJ_PNP] = I82930_Pnp;
  88. DBGPRINT(2, ("exit: DriverEntry\n"));
  89. return STATUS_SUCCESS;
  90. }
  91. //******************************************************************************
  92. //
  93. // I82930_Unload()
  94. //
  95. //******************************************************************************
  96. VOID
  97. I82930_Unload (
  98. IN PDRIVER_OBJECT DriverObject
  99. )
  100. {
  101. DBGPRINT(2, ("enter: I82930_Unload\n"));
  102. LOGENTRY('UNLD', DriverObject, 0, 0);
  103. DBGFBRK(DBGF_BRK_UNLOAD);
  104. LOGUNINIT();
  105. DBGPRINT(2, ("exit: I82930_Unload\n"));
  106. }
  107. //******************************************************************************
  108. //
  109. // I82930_AddDevice()
  110. //
  111. //******************************************************************************
  112. NTSTATUS
  113. I82930_AddDevice (
  114. IN PDRIVER_OBJECT DriverObject,
  115. IN PDEVICE_OBJECT PhysicalDeviceObject
  116. )
  117. {
  118. NTSTATUS ntStatus;
  119. PDEVICE_OBJECT deviceObject;
  120. PDEVICE_EXTENSION deviceExtension;
  121. DBGPRINT(2, ("enter: I82930_AddDevice\n"));
  122. LOGENTRY('ADDD', DriverObject, PhysicalDeviceObject, 0);
  123. DBGFBRK(DBGF_BRK_ADDDEVICE);
  124. // Create the FDO
  125. //
  126. ntStatus = IoCreateDevice(DriverObject,
  127. sizeof(DEVICE_EXTENSION),
  128. NULL,
  129. FILE_DEVICE_UNKNOWN,
  130. FILE_AUTOGENERATED_DEVICE_NAME,
  131. FALSE,
  132. &deviceObject);
  133. if (!NT_SUCCESS(ntStatus))
  134. {
  135. return ntStatus;
  136. }
  137. // Initialize the DeviceExtension
  138. //
  139. deviceExtension = deviceObject->DeviceExtension;
  140. // Set all DeviceExtension pointers to NULL and all variable to zero
  141. //
  142. RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
  143. // Remember our PDO
  144. //
  145. deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  146. // Attach the FDO we created to the top of the PDO stack
  147. //
  148. deviceExtension->StackDeviceObject = IoAttachDeviceToDeviceStack(
  149. deviceObject,
  150. PhysicalDeviceObject);
  151. // Initialize to one in AddDevice, decrement by one in REMOVE_DEVICE
  152. //
  153. deviceExtension->OpenCount = 1;
  154. // Initialize the event which is set when OpenCount is decremented to zero.
  155. //
  156. KeInitializeEvent(&deviceExtension->RemoveEvent,
  157. SynchronizationEvent,
  158. FALSE);
  159. // Set the initial system and device power states
  160. //
  161. deviceExtension->SystemPowerState = PowerSystemWorking;
  162. deviceExtension->DevicePowerState = PowerDeviceD0;
  163. deviceObject->Flags |= DO_DIRECT_IO;
  164. deviceObject->Flags |= DO_POWER_PAGABLE;
  165. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  166. DBGPRINT(2, ("exit: I82930_AddDevice\n"));
  167. LOGENTRY('addd', deviceObject, deviceExtension, deviceExtension->StackDeviceObject);
  168. return STATUS_SUCCESS;
  169. }
  170. //******************************************************************************
  171. //
  172. // I82930_Power()
  173. //
  174. // Dispatch routine which handles IRP_MJ_POWER
  175. //
  176. //******************************************************************************
  177. NTSTATUS
  178. I82930_Power (
  179. IN PDEVICE_OBJECT DeviceObject,
  180. IN PIRP Irp
  181. )
  182. {
  183. PDEVICE_EXTENSION deviceExtension;
  184. PIO_STACK_LOCATION irpStack;
  185. NTSTATUS ntStatus;
  186. PAGED_CODE();
  187. deviceExtension = DeviceObject->DeviceExtension;
  188. irpStack = IoGetCurrentIrpStackLocation(Irp);
  189. DBGPRINT(2, ("enter: I82930_Power %08X %s\n",
  190. DeviceObject,
  191. PowerMinorFunctionString(irpStack->MinorFunction)));
  192. LOGENTRY('POWR', DeviceObject, Irp, irpStack->MinorFunction);
  193. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  194. {
  195. DBGPRINT(2, ("IRP_MN_SET_POWER %s\n",
  196. (irpStack->Parameters.Power.Type == SystemPowerState) ?
  197. PowerSystemStateString(irpStack->Parameters.Power.State.SystemState) :
  198. PowerDeviceStateString(irpStack->Parameters.Power.State.DeviceState)));
  199. }
  200. if (irpStack->MinorFunction == IRP_MN_SET_POWER)
  201. {
  202. // Handle powering the FDO down and up...
  203. //
  204. ntStatus = I82930_FdoSetPower(DeviceObject,
  205. Irp);
  206. }
  207. else
  208. {
  209. // No special processing for IRP_MN_QUERY_POWER, IRP_MN_WAIT_WAKE,
  210. // or IRP_MN_POWER_SEQUENCE at this time. Just pass the request
  211. // down to the next lower driver now.
  212. //
  213. PoStartNextPowerIrp(Irp);
  214. IoSkipCurrentIrpStackLocation(Irp);
  215. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject,
  216. Irp);
  217. }
  218. DBGPRINT(2, ("exit: I82930_Power %08X\n", ntStatus));
  219. LOGENTRY('powr', ntStatus, 0, 0);
  220. return ntStatus;
  221. }
  222. //******************************************************************************
  223. //
  224. // I82930_FdoSetPower()
  225. //
  226. // Dispatch routine which handles IRP_MJ_POWER, IRP_MN_SET_POWER for the FDO
  227. //
  228. //******************************************************************************
  229. NTSTATUS
  230. I82930_FdoSetPower (
  231. IN PDEVICE_OBJECT DeviceObject,
  232. IN PIRP Irp
  233. )
  234. {
  235. PDEVICE_EXTENSION deviceExtension;
  236. PIO_STACK_LOCATION irpStack;
  237. POWER_STATE_TYPE powerType;
  238. POWER_STATE powerState;
  239. POWER_STATE newState;
  240. BOOLEAN passRequest;
  241. NTSTATUS ntStatus;
  242. PAGED_CODE();
  243. deviceExtension = DeviceObject->DeviceExtension;
  244. // Get our Irp parameters
  245. //
  246. irpStack = IoGetCurrentIrpStackLocation(Irp);
  247. powerType = irpStack->Parameters.Power.Type;
  248. powerState = irpStack->Parameters.Power.State;
  249. DBGPRINT(2, ("enter: I82930_FdoSetPower %08X %s\n",
  250. DeviceObject,
  251. (powerType == SystemPowerState) ?
  252. PowerSystemStateString(powerState.SystemState) :
  253. PowerDeviceStateString(powerState.DeviceState)));
  254. LOGENTRY('FDSP', DeviceObject, Irp, irpStack->MinorFunction);
  255. // Pass the request down here, unless we request a device state power
  256. // Irp, in which case we pass the request down in our completion routine.
  257. //
  258. passRequest = TRUE;
  259. if (powerType == SystemPowerState)
  260. {
  261. // Remember the current system state.
  262. //
  263. deviceExtension->SystemPowerState = powerState.SystemState;
  264. // Map the new system state to a new device state
  265. //
  266. if (powerState.SystemState != PowerSystemWorking)
  267. {
  268. newState.DeviceState = PowerDeviceD3;
  269. }
  270. else
  271. {
  272. newState.DeviceState = PowerDeviceD0;
  273. }
  274. // If the new device state is different than the current device
  275. // state, request a device state power Irp.
  276. //
  277. if (deviceExtension->DevicePowerState != newState.DeviceState)
  278. {
  279. DBGPRINT(2, ("Requesting power Irp %08X %08X from %s to %s\n",
  280. DeviceObject, Irp,
  281. PowerDeviceStateString(deviceExtension->DevicePowerState),
  282. PowerDeviceStateString(newState.DeviceState)));
  283. ASSERT(deviceExtension->CurrentPowerIrp == NULL);
  284. deviceExtension->CurrentPowerIrp = Irp;
  285. ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
  286. IRP_MN_SET_POWER,
  287. newState,
  288. I82930_FdoSetPowerCompletion,
  289. DeviceObject,
  290. NULL);
  291. passRequest = FALSE;
  292. }
  293. }
  294. else if (powerType == DevicePowerState)
  295. {
  296. POWER_STATE oldState;
  297. DBGPRINT(2, ("Received power Irp %08X %08X from %s to %s\n",
  298. DeviceObject, Irp,
  299. PowerDeviceStateString(deviceExtension->DevicePowerState),
  300. PowerDeviceStateString(powerState.DeviceState)));
  301. // Update the current device state.
  302. //
  303. oldState.DeviceState = deviceExtension->DevicePowerState;
  304. deviceExtension->DevicePowerState = powerState.DeviceState;
  305. if (oldState.DeviceState == PowerDeviceD0 &&
  306. powerState.DeviceState > PowerDeviceD0)
  307. {
  308. // Powering down.
  309. DBGPRINT(2, ("FDO Powering Down\n"));
  310. LOGENTRY('PWRD', DeviceObject, Irp, 0);
  311. }
  312. else if (oldState.DeviceState > PowerDeviceD0 &&
  313. powerState.DeviceState == PowerDeviceD0)
  314. {
  315. DBGPRINT(2, ("PDO Powering Up\n"));
  316. LOGENTRY('PWRU', DeviceObject, Irp, 0);
  317. }
  318. }
  319. if (passRequest)
  320. {
  321. //
  322. // Pass the request down to the next lower driver
  323. //
  324. PoStartNextPowerIrp(Irp);
  325. IoSkipCurrentIrpStackLocation(Irp);
  326. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject,
  327. Irp);
  328. }
  329. DBGPRINT(2, ("exit: I82930_FdoSetPower %08X\n", ntStatus));
  330. LOGENTRY('fdsp', ntStatus, 0, 0);
  331. return ntStatus;
  332. }
  333. //******************************************************************************
  334. //
  335. // I82930_FdoSetPowerCompletion()
  336. //
  337. // Completion routine for PoRequestPowerIrp() in I82930_FdoSetPower.
  338. //
  339. // The purpose of this routine is to block passing down the SystemPowerState
  340. // Irp until the requested DevicePowerState Irp completes.
  341. //
  342. //******************************************************************************
  343. VOID
  344. I82930_FdoSetPowerCompletion(
  345. IN PDEVICE_OBJECT PdoDeviceObject,
  346. IN UCHAR MinorFunction,
  347. IN POWER_STATE PowerState,
  348. IN PVOID Context,
  349. IN PIO_STATUS_BLOCK IoStatus
  350. )
  351. {
  352. PDEVICE_OBJECT fdoDeviceObject;
  353. PDEVICE_EXTENSION deviceExtension;
  354. PIRP irp;
  355. NTSTATUS ntStatus;
  356. fdoDeviceObject = (PDEVICE_OBJECT)Context;
  357. deviceExtension = fdoDeviceObject->DeviceExtension;
  358. ASSERT(deviceExtension->CurrentPowerIrp != NULL);
  359. irp = deviceExtension->CurrentPowerIrp;
  360. deviceExtension->CurrentPowerIrp = NULL;
  361. #if DBG
  362. {
  363. PIO_STACK_LOCATION irpStack;
  364. SYSTEM_POWER_STATE systemState;
  365. irpStack = IoGetCurrentIrpStackLocation(irp);
  366. systemState = irpStack->Parameters.Power.State.SystemState;
  367. ntStatus = IoStatus->Status;
  368. DBGPRINT(2, ("I82930_FdoSetPowerCompletion %08X %08X %s %08X\n",
  369. fdoDeviceObject, irp,
  370. PowerSystemStateString(systemState),
  371. ntStatus));
  372. LOGENTRY('fspc', fdoDeviceObject, systemState, ntStatus);
  373. }
  374. #endif
  375. // The requested DevicePowerState Irp has completed.
  376. // Now pass down the SystemPowerState Irp which requested the
  377. // DevicePowerState Irp.
  378. PoStartNextPowerIrp(irp);
  379. IoSkipCurrentIrpStackLocation(irp);
  380. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject,
  381. irp);
  382. }
  383. //******************************************************************************
  384. //
  385. // I82930_SystemControl()
  386. //
  387. // Dispatch routine which handles IRP_MJ_SYSTEM_CONTROL
  388. //
  389. //******************************************************************************
  390. NTSTATUS
  391. I82930_SystemControl (
  392. IN PDEVICE_OBJECT DeviceObject,
  393. IN PIRP Irp
  394. )
  395. {
  396. NTSTATUS ntStatus;
  397. PDEVICE_EXTENSION deviceExtension;
  398. PIO_STACK_LOCATION irpStack;
  399. deviceExtension = DeviceObject->DeviceExtension;
  400. irpStack = IoGetCurrentIrpStackLocation(Irp);
  401. DBGPRINT(2, ("enter: I82930_SystemControl %2X\n", irpStack->MinorFunction));
  402. LOGENTRY('SYSC', DeviceObject, Irp, irpStack->MinorFunction);
  403. switch (irpStack->MinorFunction)
  404. {
  405. //
  406. // XXXXX Need to handle any of these?
  407. //
  408. default:
  409. //
  410. // Pass the request down to the next lower driver
  411. //
  412. IoSkipCurrentIrpStackLocation(Irp);
  413. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  414. Irp);
  415. break;
  416. }
  417. DBGPRINT(2, ("exit: I82930_SystemControl %08X\n", ntStatus));
  418. LOGENTRY('sysc', ntStatus, 0, 0);
  419. return ntStatus;
  420. }
  421. //******************************************************************************
  422. //
  423. // I82930_Pnp()
  424. //
  425. // Dispatch routine which handles IRP_MJ_PNP
  426. //
  427. //******************************************************************************
  428. NTSTATUS
  429. I82930_Pnp (
  430. IN PDEVICE_OBJECT DeviceObject,
  431. IN PIRP Irp
  432. )
  433. {
  434. NTSTATUS ntStatus;
  435. PDEVICE_EXTENSION deviceExtension;
  436. PIO_STACK_LOCATION irpStack;
  437. deviceExtension = DeviceObject->DeviceExtension;
  438. irpStack = IoGetCurrentIrpStackLocation(Irp);
  439. DBGPRINT(2, ("enter: I82930_Pnp %s\n",
  440. PnPMinorFunctionString(irpStack->MinorFunction)));
  441. LOGENTRY('PNP ', DeviceObject, Irp, irpStack->MinorFunction);
  442. switch (irpStack->MinorFunction)
  443. {
  444. case IRP_MN_START_DEVICE:
  445. ntStatus = I82930_StartDevice(DeviceObject, Irp);
  446. break;
  447. case IRP_MN_STOP_DEVICE:
  448. ntStatus = I82930_StopDevice(DeviceObject, Irp);
  449. break;
  450. case IRP_MN_REMOVE_DEVICE:
  451. ntStatus = I82930_RemoveDevice(DeviceObject, Irp);
  452. break;
  453. case IRP_MN_QUERY_STOP_DEVICE:
  454. case IRP_MN_QUERY_REMOVE_DEVICE:
  455. ntStatus = I82930_QueryStopRemoveDevice(DeviceObject, Irp);
  456. break;
  457. case IRP_MN_CANCEL_STOP_DEVICE:
  458. case IRP_MN_CANCEL_REMOVE_DEVICE:
  459. ntStatus = I82930_CancelStopRemoveDevice(DeviceObject, Irp);
  460. break;
  461. case IRP_MN_QUERY_CAPABILITIES:
  462. ntStatus = I82930_QueryCapabilities(DeviceObject, Irp);
  463. break;
  464. case IRP_MN_SURPRISE_REMOVAL:
  465. // nothing special yet, just fall through to default
  466. default:
  467. //
  468. // Pass the request down to the next lower driver
  469. //
  470. IoSkipCurrentIrpStackLocation(Irp);
  471. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  472. Irp);
  473. break;
  474. }
  475. DBGPRINT(2, ("exit: I82930_Pnp %08X\n", ntStatus));
  476. LOGENTRY('pnp ', ntStatus, 0, 0);
  477. return ntStatus;
  478. }
  479. //******************************************************************************
  480. //
  481. // I82930_StartDevice()
  482. //
  483. // This routine handles IRP_MJ_PNP, IRP_MN_START_DEVICE
  484. //
  485. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  486. // system thread.
  487. //
  488. // This IRP must be handled first by the underlying bus driver for a device
  489. // and then by each higher driver in the device stack.
  490. //
  491. // Device specific actions:
  492. // Retrieve the Device Descriptor from device (first time only)
  493. // Retrieve the Configuration Descriptor from device (first time only)
  494. // Configure the device (every time)
  495. // Create the SymbolicLink name (first time only)
  496. // Enable the SymbolicLink name (every time)
  497. //
  498. //******************************************************************************
  499. NTSTATUS
  500. I82930_StartDevice (
  501. IN PDEVICE_OBJECT DeviceObject,
  502. IN PIRP Irp
  503. )
  504. {
  505. PDEVICE_EXTENSION deviceExtension;
  506. PUCHAR descriptor;
  507. ULONG descriptorLength;
  508. NTSTATUS ntStatus;
  509. DBGPRINT(2, ("enter: I82930_StartDevice\n"));
  510. DBGFBRK(DBGF_BRK_STARTDEVICE);
  511. LOGENTRY('STRT', DeviceObject, Irp, 0);
  512. deviceExtension = DeviceObject->DeviceExtension;
  513. // Pass IRP_MN_START_DEVICE Irp down the stack first before we do anything.
  514. //
  515. ntStatus = I82930_SyncPassDownIrp(DeviceObject,
  516. Irp,
  517. TRUE);
  518. if (!NT_SUCCESS(ntStatus))
  519. {
  520. DBGPRINT(1, ("Lower driver failed IRP_MN_START_DEVICE\n"));
  521. goto I82930_StartDeviceDone;
  522. }
  523. //
  524. // If this is the first time the device as been started, retrieve the
  525. // Device and Configuration Descriptors from the device.
  526. //
  527. if (deviceExtension->DeviceDescriptor == NULL)
  528. {
  529. //
  530. // Get Device Descriptor
  531. //
  532. ntStatus = I82930_GetDescriptor(DeviceObject,
  533. USB_RECIPIENT_DEVICE,
  534. USB_DEVICE_DESCRIPTOR_TYPE,
  535. 0, // Index
  536. 0, // LanguageId
  537. 2, // RetryCount
  538. sizeof(USB_DEVICE_DESCRIPTOR),
  539. &descriptor);
  540. if (!NT_SUCCESS(ntStatus))
  541. {
  542. DBGPRINT(1, ("Get Device Descriptor failed\n"));
  543. Irp->IoStatus.Status = ntStatus;
  544. goto I82930_StartDeviceDone;
  545. }
  546. deviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;
  547. //
  548. // Get Configuration Descriptor (just the Configuration Descriptor)
  549. //
  550. ntStatus = I82930_GetDescriptor(DeviceObject,
  551. USB_RECIPIENT_DEVICE,
  552. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  553. 0, // Index
  554. 0, // LanguageId
  555. 2, // RetryCount
  556. sizeof(USB_CONFIGURATION_DESCRIPTOR),
  557. &descriptor);
  558. if (!NT_SUCCESS(ntStatus))
  559. {
  560. DBGPRINT(1, ("Get Configuration Descriptor failed (1)\n"));
  561. Irp->IoStatus.Status = ntStatus;
  562. goto I82930_StartDeviceDone;
  563. }
  564. descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;
  565. ExFreePool(descriptor);
  566. if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
  567. {
  568. ntStatus = STATUS_DEVICE_DATA_ERROR;
  569. DBGPRINT(1, ("Get Configuration Descriptor failed (2)\n"));
  570. Irp->IoStatus.Status = ntStatus;
  571. goto I82930_StartDeviceDone;
  572. }
  573. //
  574. // Get Configuration Descriptor (and Interface and Endpoint Descriptors)
  575. //
  576. ntStatus = I82930_GetDescriptor(DeviceObject,
  577. USB_RECIPIENT_DEVICE,
  578. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  579. 0, // Index
  580. 0, // LanguageId
  581. 2, // RetryCount
  582. descriptorLength,
  583. &descriptor);
  584. if (!NT_SUCCESS(ntStatus))
  585. {
  586. DBGPRINT(1, ("Get Configuration Descriptor failed (3)\n"));
  587. Irp->IoStatus.Status = ntStatus;
  588. goto I82930_StartDeviceDone;
  589. }
  590. deviceExtension->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;
  591. #if DBG
  592. DumpDeviceDesc(deviceExtension->DeviceDescriptor);
  593. DumpConfigDesc(deviceExtension->ConfigurationDescriptor);
  594. #endif
  595. }
  596. // Now configure the device
  597. //
  598. ntStatus = I82930_SelectConfiguration(DeviceObject);
  599. if (!NT_SUCCESS(ntStatus))
  600. {
  601. DBGPRINT(1, ("Configure device failed\n"));
  602. Irp->IoStatus.Status = ntStatus;
  603. goto I82930_StartDeviceDone;
  604. }
  605. // Create the SymbolicLink name if necessary
  606. //
  607. if (deviceExtension->SymbolicLinkName.Buffer == NULL)
  608. {
  609. ntStatus = IoRegisterDeviceInterface(
  610. deviceExtension->PhysicalDeviceObject,
  611. (LPGUID)&GUID_CLASS_I82930,
  612. NULL,
  613. &deviceExtension->SymbolicLinkName);
  614. if (!NT_SUCCESS(ntStatus))
  615. {
  616. DBGPRINT(1, ("IoRegisterDeviceInterface failed\n"));
  617. Irp->IoStatus.Status = ntStatus;
  618. goto I82930_StartDeviceDone;
  619. }
  620. }
  621. // All set for user requests at this point
  622. //
  623. deviceExtension->AcceptingRequests = TRUE;
  624. // Enable the SymbolicLink name
  625. //
  626. ntStatus = IoSetDeviceInterfaceState(
  627. &deviceExtension->SymbolicLinkName,
  628. TRUE);
  629. if (!NT_SUCCESS(ntStatus))
  630. {
  631. DBGPRINT(1, ("IoSetDeviceInterfaceState failed\n"));
  632. Irp->IoStatus.Status = ntStatus;
  633. goto I82930_StartDeviceDone;
  634. }
  635. I82930_StartDeviceDone:
  636. // Must complete request since completion routine returned
  637. // STATUS_MORE_PROCESSING_REQUIRED
  638. //
  639. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  640. DBGPRINT(2, ("exit: I82930_StartDevice %08X\n", ntStatus));
  641. LOGENTRY('strt', ntStatus, 0, 0);
  642. return ntStatus;
  643. }
  644. //******************************************************************************
  645. //
  646. // I82930_StopDevice()
  647. //
  648. // This routine handles IRP_MJ_PNP, IRP_MN_STOP_DEVICE
  649. //
  650. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  651. // system thread.
  652. //
  653. // The PnP Manager only sends this IRP if a prior IRP_MN_QUERY_STOP_DEVICE
  654. // completed successfully.
  655. //
  656. // This IRP is handled first by the driver at the top of the device stack and
  657. // then by each lower driver in the attachment chain.
  658. //
  659. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. A driver must
  660. // not fail this IRP. If a driver cannot release the device's hardware
  661. // resources, it can fail a query-stop IRP, but once it succeeds the query-stop
  662. // request it must succeed the stop request.
  663. //
  664. //******************************************************************************
  665. NTSTATUS
  666. I82930_StopDevice (
  667. IN PDEVICE_OBJECT DeviceObject,
  668. IN PIRP Irp
  669. )
  670. {
  671. PDEVICE_EXTENSION deviceExtension;
  672. NTSTATUS ntStatus;
  673. DBGPRINT(2, ("enter: I82930_StopDevice\n"));
  674. LOGENTRY('STOP', DeviceObject, Irp, 0);
  675. DBGFBRK(DBGF_BRK_STOPDEVICE);
  676. deviceExtension = DeviceObject->DeviceExtension;
  677. // Release the device resources allocated during IRP_MN_START_DEVICE
  678. //
  679. // Unconfigure the device
  680. //
  681. ntStatus = I82930_UnConfigure(DeviceObject);
  682. // Pass the IRP_MN_STOP_DEVICE Irp down the stack.
  683. //
  684. IoSkipCurrentIrpStackLocation(Irp);
  685. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  686. Irp);
  687. DBGPRINT(2, ("exit: I82930_StopDevice %08X\n", ntStatus));
  688. LOGENTRY('stop', ntStatus, 0, 0);
  689. return ntStatus;
  690. }
  691. //******************************************************************************
  692. //
  693. // I82930_RemoveDevice()
  694. //
  695. // This routine handles IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE
  696. //
  697. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  698. // system thread.
  699. //
  700. // This IRP is handled first by the driver at the top of the device stack and
  701. // then by each lower driver in the attachment chain.
  702. //
  703. // A driver must set Irp->IoStatus.Status to STATUS_SUCCESS. Drivers must not
  704. // fail this IRP.
  705. //
  706. //******************************************************************************
  707. NTSTATUS
  708. I82930_RemoveDevice (
  709. IN PDEVICE_OBJECT DeviceObject,
  710. IN PIRP Irp
  711. )
  712. {
  713. PDEVICE_EXTENSION deviceExtension;
  714. NTSTATUS ntStatus;
  715. DBGPRINT(2, ("enter: I82930_RemoveDevice\n"));
  716. LOGENTRY('REMV', DeviceObject, Irp, 0);
  717. DBGFBRK(DBGF_BRK_REMOVEDEVICE);
  718. deviceExtension = DeviceObject->DeviceExtension;
  719. // Disable and free the SymbolicLink name if necessary
  720. //
  721. if (deviceExtension->SymbolicLinkName.Buffer != NULL)
  722. {
  723. ntStatus = IoSetDeviceInterfaceState(
  724. &deviceExtension->SymbolicLinkName,
  725. FALSE);
  726. RtlFreeUnicodeString(&deviceExtension->SymbolicLinkName);
  727. }
  728. // No more user requests at this point
  729. //
  730. deviceExtension->AcceptingRequests = FALSE;
  731. // Abort any requests that may be lingering on any of the endpoints.
  732. //
  733. if (deviceExtension->InterfaceInfo != NULL)
  734. {
  735. ULONG pipeIndex;
  736. ULONG numPipes;
  737. numPipes = deviceExtension->InterfaceInfo->NumberOfPipes;
  738. for (pipeIndex = 0; pipeIndex < numPipes; pipeIndex++)
  739. {
  740. I82930_AbortPipe(DeviceObject,
  741. &deviceExtension->PipeList[pipeIndex]);
  742. }
  743. }
  744. // Decrement by one to match the initial one in AddDevice
  745. //
  746. DECREMENT_OPEN_COUNT(deviceExtension);
  747. LOGENTRY('rem1', DeviceObject, 0, 0);
  748. // Wait for all pending requests to complete
  749. //
  750. KeWaitForSingleObject(&deviceExtension->RemoveEvent,
  751. Executive,
  752. KernelMode,
  753. FALSE,
  754. NULL);
  755. LOGENTRY('rem2', DeviceObject, 0, 0);
  756. // Free everything that was allocated during IRP_MN_START_DEVICE
  757. //
  758. if (deviceExtension->DeviceDescriptor != NULL)
  759. {
  760. ExFreePool(deviceExtension->DeviceDescriptor);
  761. }
  762. if (deviceExtension->ConfigurationDescriptor != NULL)
  763. {
  764. ExFreePool(deviceExtension->ConfigurationDescriptor);
  765. }
  766. if (deviceExtension->InterfaceInfo != NULL)
  767. {
  768. ExFreePool(deviceExtension->InterfaceInfo);
  769. }
  770. // The documentation says to set the status before passing the Irp down
  771. //
  772. Irp->IoStatus.Status = STATUS_SUCCESS;
  773. // Pass the IRP_MN_REMOVE_DEVICE Irp down the stack.
  774. //
  775. IoSkipCurrentIrpStackLocation(Irp);
  776. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  777. Irp);
  778. LOGENTRY('rem3', DeviceObject, 0, 0);
  779. // Free everything that was allocated during AddDevice
  780. //
  781. IoDetachDevice(deviceExtension->StackDeviceObject);
  782. IoDeleteDevice(DeviceObject);
  783. DBGPRINT(2, ("exit: I82930_RemoveDevice %08X\n", ntStatus));
  784. LOGENTRY('remv', ntStatus, 0, 0);
  785. return ntStatus;
  786. }
  787. //******************************************************************************
  788. //
  789. // I82930_QueryStopRemoveDevice()
  790. //
  791. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE and
  792. // IRP_MN_QUERY_REMOVE_DEVICE.
  793. //
  794. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  795. // system thread.
  796. //
  797. // This IRP is handled first by the driver at the top of the device stack and
  798. // then by each lower driver in the attachment chain.
  799. //
  800. //******************************************************************************
  801. NTSTATUS
  802. I82930_QueryStopRemoveDevice (
  803. IN PDEVICE_OBJECT DeviceObject,
  804. IN PIRP Irp
  805. )
  806. {
  807. PDEVICE_EXTENSION deviceExtension;
  808. NTSTATUS ntStatus;
  809. DBGPRINT(2, ("enter: I82930_QueryStopRemoveDevice\n"));
  810. LOGENTRY('QSRD', DeviceObject, Irp, 0);
  811. DBGFBRK(DBGF_BRK_QUERYSTOPDEVICE);
  812. deviceExtension = DeviceObject->DeviceExtension;
  813. // Disable the SymbolicLink name
  814. //
  815. ntStatus = IoSetDeviceInterfaceState(
  816. &deviceExtension->SymbolicLinkName,
  817. FALSE);
  818. // No more user requests at this point
  819. //
  820. deviceExtension->AcceptingRequests = FALSE;
  821. // If there are no opens, OK to STOP or REMOVE
  822. //
  823. if (deviceExtension->OpenCount == 1)
  824. {
  825. LOGENTRY('qsr1', 0, 0, 0);
  826. // The documentation says to set the status before passing the Irp down
  827. //
  828. Irp->IoStatus.Status = STATUS_SUCCESS;
  829. // Pass the IRP_MN_QUERY_STOP/REMOVE_DEVICE Irp down the stack.
  830. //
  831. IoSkipCurrentIrpStackLocation(Irp);
  832. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  833. Irp);
  834. }
  835. else
  836. {
  837. LOGENTRY('qsr2', deviceExtension->OpenCount, 0, 0);
  838. ntStatus = STATUS_DEVICE_BUSY;
  839. Irp->IoStatus.Status = ntStatus;
  840. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  841. }
  842. DBGPRINT(2, ("exit: I82930_QueryStopRemoveDevice %08X\n", ntStatus));
  843. LOGENTRY('qsrd', ntStatus, 0, 0);
  844. return ntStatus;
  845. }
  846. //******************************************************************************
  847. //
  848. // I82930_CancelStopRemoveDevice()
  849. //
  850. // This routine handles IRP_MJ_PNP, IRP_MN_CANCEL_STOP_DEVICE and
  851. // IRP_MN_CANCEL_REMOVE_DEVICE.
  852. //
  853. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  854. // system thread.
  855. //
  856. // This IRP must be handled first by the underlying bus driver for a device
  857. // and then by each higher driver in the device stack.
  858. //
  859. //******************************************************************************
  860. NTSTATUS
  861. I82930_CancelStopRemoveDevice (
  862. IN PDEVICE_OBJECT DeviceObject,
  863. IN PIRP Irp
  864. )
  865. {
  866. PDEVICE_EXTENSION deviceExtension;
  867. NTSTATUS ntStatus;
  868. DBGPRINT(2, ("enter: I82930_CancelStopRemoveDevice\n"));
  869. LOGENTRY('CSRD', DeviceObject, Irp, 0);
  870. DBGFBRK(DBGF_BRK_CANCELSTOPDEVICE);
  871. deviceExtension = DeviceObject->DeviceExtension;
  872. // Pass the IRP_MN_CANCEL_STOP/REMOVE_DEVICE Irp down the stack first.
  873. //
  874. ntStatus = I82930_SyncPassDownIrp(DeviceObject,
  875. Irp,
  876. TRUE);
  877. if (!NT_SUCCESS(ntStatus))
  878. {
  879. DBGPRINT(1, ("Lower driver failed IRP_MN_CANCEL_STOP/REMOVE_DEVICE\n"));
  880. goto I82930_CancelStopRemoveDeviceDone;
  881. }
  882. // All set for user requests at this point
  883. //
  884. deviceExtension->AcceptingRequests = TRUE;
  885. // Enable the SymbolicLink name
  886. //
  887. ntStatus = IoSetDeviceInterfaceState(
  888. &deviceExtension->SymbolicLinkName,
  889. TRUE);
  890. if (!NT_SUCCESS(ntStatus))
  891. {
  892. DBGPRINT(1, ("IoSetDeviceInterfaceState failed\n"));
  893. Irp->IoStatus.Status = ntStatus;
  894. goto I82930_CancelStopRemoveDeviceDone;
  895. }
  896. I82930_CancelStopRemoveDeviceDone:
  897. // Must complete request since completion routine returned
  898. // STATUS_MORE_PROCESSING_REQUIRED
  899. //
  900. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  901. DBGPRINT(2, ("exit: I82930_CancelStopRemoveDevice %08X\n", ntStatus));
  902. LOGENTRY('csrd', ntStatus, 0, 0);
  903. return ntStatus;
  904. }
  905. //******************************************************************************
  906. //
  907. // I82930_QueryCapabilities()
  908. //
  909. // This routine handles IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES.
  910. //
  911. // The PnP Manager sends this IRP at IRQL PASSIVE_LEVEL in the context of a
  912. // an arbitrary thread.
  913. //
  914. //******************************************************************************
  915. NTSTATUS
  916. I82930_QueryCapabilities (
  917. IN PDEVICE_OBJECT DeviceObject,
  918. IN PIRP Irp
  919. )
  920. {
  921. PIO_STACK_LOCATION irpStack;
  922. PDEVICE_CAPABILITIES deviceCapabilities;
  923. NTSTATUS ntStatus;
  924. PAGED_CODE();
  925. DBGPRINT(2, ("enter: I82930_QueryCapabilities\n"));
  926. LOGENTRY('FQCP', DeviceObject, Irp, 0);
  927. irpStack = IoGetCurrentIrpStackLocation(Irp);
  928. deviceCapabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  929. // Pass IRP_MN_QUERY_CAPABILITIES Irp down the stack first before we do
  930. // anything.
  931. //
  932. ntStatus = I82930_SyncPassDownIrp(DeviceObject,
  933. Irp,
  934. TRUE);
  935. if (!NT_SUCCESS(ntStatus))
  936. {
  937. DBGPRINT(1, ("Lower driver failed IRP_MN_QUERY_CAPABILITIES\n"));
  938. }
  939. else
  940. {
  941. deviceCapabilities->SurpriseRemovalOK = TRUE;
  942. }
  943. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  944. DBGPRINT(2, ("exit: I82930_QueryCapabilities %08X\n", ntStatus));
  945. LOGENTRY('fqcp', ntStatus, 0, 0);
  946. return ntStatus;
  947. }
  948. //******************************************************************************
  949. //
  950. // I82930_SyncPassDownIrp()
  951. //
  952. //******************************************************************************
  953. NTSTATUS
  954. I82930_SyncPassDownIrp (
  955. IN PDEVICE_OBJECT DeviceObject,
  956. IN PIRP Irp,
  957. IN BOOLEAN CopyToNext
  958. )
  959. {
  960. PDEVICE_EXTENSION deviceExtension;
  961. NTSTATUS ntStatus;
  962. KEVENT localevent;
  963. DBGPRINT(2, ("enter: I82930_SyncPassDownIrp\n"));
  964. deviceExtension = DeviceObject->DeviceExtension;
  965. // Initialize the event we'll wait on
  966. //
  967. KeInitializeEvent(&localevent,
  968. SynchronizationEvent,
  969. FALSE);
  970. if (CopyToNext)
  971. {
  972. // Next Stack Location not set up, copy Current Stack Location
  973. // to the Next Stack Location.
  974. //
  975. IoCopyCurrentIrpStackLocationToNext(Irp);
  976. }
  977. // Set the completion routine, which will signal the event
  978. //
  979. IoSetCompletionRoutine(Irp,
  980. I82930_SyncCompletionRoutine,
  981. &localevent,
  982. TRUE, // InvokeOnSuccess
  983. TRUE, // InvokeOnError
  984. TRUE); // InvokeOnCancel
  985. // Pass the Irp down the stack
  986. //
  987. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  988. Irp);
  989. // If the request is pending, block until it completes
  990. //
  991. if (ntStatus == STATUS_PENDING)
  992. {
  993. KeWaitForSingleObject(&localevent,
  994. Executive,
  995. KernelMode,
  996. FALSE,
  997. NULL);
  998. ntStatus = Irp->IoStatus.Status;
  999. }
  1000. DBGPRINT(2, ("exit: I82930_SyncPassDownIrp %08X\n", ntStatus));
  1001. return ntStatus;
  1002. }
  1003. //******************************************************************************
  1004. //
  1005. // I82930_SyncCompletionRoutine()
  1006. //
  1007. // Completion routine used by I82930_SyncPassDownIrp and
  1008. // I82930_SyncSendUsbRequest
  1009. //
  1010. // If the Irp is one we allocated ourself, DeviceObject is NULL unless we
  1011. // allocated a stack location for ourself and initialized the DeviceObject
  1012. // pointer in our stack location.
  1013. //
  1014. //******************************************************************************
  1015. NTSTATUS
  1016. I82930_SyncCompletionRoutine (
  1017. IN PDEVICE_OBJECT DeviceObject,
  1018. IN PIRP Irp,
  1019. IN PVOID Context
  1020. )
  1021. {
  1022. PKEVENT kevent;
  1023. LOGENTRY('SCR ', DeviceObject, Irp, Irp->IoStatus.Status);
  1024. kevent = (PKEVENT)Context;
  1025. KeSetEvent(kevent,
  1026. IO_NO_INCREMENT,
  1027. FALSE);
  1028. return STATUS_MORE_PROCESSING_REQUIRED;
  1029. }
  1030. //******************************************************************************
  1031. //
  1032. // I82930_SyncSendUsbRequest()
  1033. //
  1034. // Must be called at IRQL <= DISPATCH_LEVEL
  1035. //
  1036. //******************************************************************************
  1037. NTSTATUS
  1038. I82930_SyncSendUsbRequest (
  1039. IN PDEVICE_OBJECT DeviceObject,
  1040. IN PURB Urb
  1041. )
  1042. {
  1043. PDEVICE_EXTENSION deviceExtension;
  1044. KEVENT localevent;
  1045. PIRP irp;
  1046. PIO_STACK_LOCATION nextStack;
  1047. NTSTATUS ntStatus;
  1048. DBGPRINT(3, ("enter: I82930_SyncSendUsbRequest\n"));
  1049. deviceExtension = DeviceObject->DeviceExtension;
  1050. // Initialize the event we'll wait on
  1051. //
  1052. KeInitializeEvent(&localevent,
  1053. SynchronizationEvent,
  1054. FALSE);
  1055. // Allocate the Irp
  1056. //
  1057. irp = IoAllocateIrp(deviceExtension->StackDeviceObject->StackSize, FALSE);
  1058. LOGENTRY('SSUR', DeviceObject, irp, Urb);
  1059. if (irp == NULL)
  1060. {
  1061. return STATUS_INSUFFICIENT_RESOURCES;
  1062. }
  1063. // Set the Irp parameters
  1064. //
  1065. nextStack = IoGetNextIrpStackLocation(irp);
  1066. nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1067. nextStack->Parameters.DeviceIoControl.IoControlCode =
  1068. IOCTL_INTERNAL_USB_SUBMIT_URB;
  1069. nextStack->Parameters.Others.Argument1 = Urb;
  1070. // Set the completion routine, which will signal the event
  1071. //
  1072. IoSetCompletionRoutine(irp,
  1073. I82930_SyncCompletionRoutine,
  1074. &localevent,
  1075. TRUE, // InvokeOnSuccess
  1076. TRUE, // InvokeOnError
  1077. TRUE); // InvokeOnCancel
  1078. // Pass the Irp & Urb down the stack
  1079. //
  1080. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  1081. irp);
  1082. // If the request is pending, block until it completes
  1083. //
  1084. if (ntStatus == STATUS_PENDING)
  1085. {
  1086. LARGE_INTEGER timeout;
  1087. // Specify a timeout of 5 seconds to wait for this call to complete.
  1088. //
  1089. timeout.QuadPart = -10000 * 5000;
  1090. ntStatus = KeWaitForSingleObject(&localevent,
  1091. Executive,
  1092. KernelMode,
  1093. FALSE,
  1094. &timeout);
  1095. if (ntStatus == STATUS_TIMEOUT)
  1096. {
  1097. ntStatus = STATUS_IO_TIMEOUT;
  1098. // Cancel the Irp we just sent.
  1099. //
  1100. IoCancelIrp(irp);
  1101. // And wait until the cancel completes
  1102. //
  1103. KeWaitForSingleObject(&localevent,
  1104. Executive,
  1105. KernelMode,
  1106. FALSE,
  1107. NULL);
  1108. }
  1109. else
  1110. {
  1111. ntStatus = irp->IoStatus.Status;
  1112. }
  1113. }
  1114. // Done with the Irp, now free it.
  1115. //
  1116. IoFreeIrp(irp);
  1117. LOGENTRY('ssur', ntStatus, Urb, Urb->UrbHeader.Status);
  1118. DBGPRINT(3, ("exit: I82930_SyncSendUsbRequest %08X\n", ntStatus));
  1119. return ntStatus;
  1120. }
  1121. //******************************************************************************
  1122. //
  1123. // I82930_GetDescriptor()
  1124. //
  1125. // Must be called at IRQL <= DISPATCH_LEVEL
  1126. //
  1127. //******************************************************************************
  1128. NTSTATUS
  1129. I82930_GetDescriptor (
  1130. IN PDEVICE_OBJECT DeviceObject,
  1131. IN UCHAR Recipient,
  1132. IN UCHAR DescriptorType,
  1133. IN UCHAR Index,
  1134. IN USHORT LanguageId,
  1135. IN ULONG RetryCount,
  1136. IN ULONG DescriptorLength,
  1137. OUT PUCHAR *Descriptor
  1138. )
  1139. {
  1140. USHORT function;
  1141. PURB urb;
  1142. NTSTATUS ntStatus;
  1143. DBGPRINT(2, ("enter: I82930_GetDescriptor\n"));
  1144. // Set the URB function based on Recipient {Device, Interface, Endpoint}
  1145. //
  1146. switch (Recipient)
  1147. {
  1148. case USB_RECIPIENT_DEVICE:
  1149. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
  1150. break;
  1151. case USB_RECIPIENT_INTERFACE:
  1152. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
  1153. break;
  1154. case USB_RECIPIENT_ENDPOINT:
  1155. function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
  1156. break;
  1157. default:
  1158. *Descriptor = NULL;
  1159. return STATUS_INVALID_PARAMETER;
  1160. }
  1161. // Allocate a descriptor buffer
  1162. //
  1163. *Descriptor = ExAllocatePoolWithTag(NonPagedPool,
  1164. DescriptorLength,
  1165. POOL_TAG);
  1166. if (*Descriptor != NULL)
  1167. {
  1168. // Allocate a URB for the Get Descriptor request
  1169. //
  1170. urb = ExAllocatePoolWithTag(NonPagedPool,
  1171. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1172. POOL_TAG);
  1173. if (urb != NULL)
  1174. {
  1175. do
  1176. {
  1177. // Initialize the URB
  1178. //
  1179. urb->UrbHeader.Function = function;
  1180. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
  1181. urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
  1182. urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
  1183. urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
  1184. urb->UrbControlDescriptorRequest.UrbLink = NULL;
  1185. urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
  1186. urb->UrbControlDescriptorRequest.Index = Index;
  1187. urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
  1188. // Send the URB down the stack
  1189. //
  1190. ntStatus = I82930_SyncSendUsbRequest(DeviceObject,
  1191. urb);
  1192. if (NT_SUCCESS(ntStatus))
  1193. {
  1194. // No error, make sure the length and type are correct
  1195. //
  1196. if ((DescriptorLength ==
  1197. urb->UrbControlDescriptorRequest.TransferBufferLength) &&
  1198. (DescriptorType ==
  1199. ((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
  1200. {
  1201. // The length and type are correct, all done
  1202. //
  1203. break;
  1204. }
  1205. else
  1206. {
  1207. // No error, but the length or type is incorrect
  1208. //
  1209. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1210. }
  1211. }
  1212. } while (RetryCount-- > 0);
  1213. ExFreePool(urb);
  1214. }
  1215. else
  1216. {
  1217. // Failed to allocate the URB
  1218. //
  1219. ExFreePool(*Descriptor);
  1220. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1221. }
  1222. }
  1223. else
  1224. {
  1225. // Failed to allocate the descriptor buffer
  1226. //
  1227. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1228. }
  1229. if (!NT_SUCCESS(ntStatus))
  1230. {
  1231. *Descriptor = NULL;
  1232. }
  1233. DBGPRINT(2, ("exit: I82930_GetDescriptor %08X\n", ntStatus));
  1234. return ntStatus;
  1235. }
  1236. //******************************************************************************
  1237. //
  1238. // I82930_SelectConfiguration()
  1239. //
  1240. // Must be called at IRQL <= DISPATCH_LEVEL
  1241. //
  1242. //******************************************************************************
  1243. NTSTATUS
  1244. I82930_SelectConfiguration (
  1245. IN PDEVICE_OBJECT DeviceObject
  1246. )
  1247. {
  1248. NTSTATUS ntStatus;
  1249. PURB urb;
  1250. ULONG i;
  1251. PDEVICE_EXTENSION deviceExtension;
  1252. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  1253. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  1254. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  1255. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  1256. DBGPRINT(2, ("enter: I82930_SelectConfiguration\n"));
  1257. LOGENTRY('SCON', DeviceObject, 0, 0);
  1258. deviceExtension = DeviceObject->DeviceExtension;
  1259. configurationDescriptor = deviceExtension->ConfigurationDescriptor;
  1260. // Allocate storage for an Inteface List to use as an input/output
  1261. // parameter to USBD_CreateConfigurationRequestEx().
  1262. //
  1263. interfaceList = ExAllocatePool(
  1264. PagedPool,
  1265. sizeof(USBD_INTERFACE_LIST_ENTRY) * 2
  1266. );
  1267. if (interfaceList)
  1268. {
  1269. // Parse the ConfigurationDescriptor (including all Interface and
  1270. // Endpoint Descriptors) and locate a Interface Descriptor which
  1271. // matches the InterfaceNumber, AlternateSetting, InterfaceClass,
  1272. // InterfaceSubClass, and InterfaceProtocol parameters. In our case
  1273. // we just grab the first Interface Descriptor from the Configuration
  1274. // Descriptor.
  1275. //
  1276. interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
  1277. configurationDescriptor,
  1278. configurationDescriptor,
  1279. -1, // InterfaceNumber, don't care
  1280. -1, // AlternateSetting, don't care
  1281. -1, // InterfaceClass, don't care
  1282. -1, // InterfaceSubClass, don't care
  1283. -1 // InterfaceProtocol, don't care
  1284. );
  1285. if (interfaceDescriptor)
  1286. {
  1287. // Add the single Interface Descriptor we care about to the
  1288. // interface list, then terminate the list.
  1289. //
  1290. interfaceList[0].InterfaceDescriptor = interfaceDescriptor;
  1291. interfaceList[1].InterfaceDescriptor = NULL;
  1292. // Create a SELECT_CONFIGURATION URB, turning the Interface
  1293. // Descriptors in the interfaceList into USBD_INTERFACE_INFORMATION
  1294. // structures in the URB.
  1295. //
  1296. urb = USBD_CreateConfigurationRequestEx(
  1297. configurationDescriptor,
  1298. interfaceList
  1299. );
  1300. if (urb)
  1301. {
  1302. interfaceInfo = &urb->UrbSelectConfiguration.Interface;
  1303. // Override the USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE
  1304. // for all pipes.
  1305. //
  1306. for (i = 0; i < interfaceInfo->NumberOfPipes; i++)
  1307. {
  1308. interfaceInfo->Pipes[i].MaximumTransferSize = 0x10000;
  1309. }
  1310. // Now issue the USB request to set the Configuration
  1311. //
  1312. ntStatus = I82930_SyncSendUsbRequest(DeviceObject,
  1313. urb);
  1314. if (NT_SUCCESS(ntStatus))
  1315. {
  1316. // Save the configuration handle for this device in
  1317. // the Device Extension.
  1318. //
  1319. deviceExtension->ConfigurationHandle =
  1320. urb->UrbSelectConfiguration.ConfigurationHandle;
  1321. // Save a copy of the interface information returned
  1322. // by the SELECT_CONFIGURATION request in the Device
  1323. // Extension. This gives us a list of PIPE_INFORMATION
  1324. // structures for each pipe opened in this configuration.
  1325. //
  1326. ASSERT(deviceExtension->InterfaceInfo == NULL);
  1327. deviceExtension->InterfaceInfo = ExAllocatePool(
  1328. PagedPool,
  1329. interfaceInfo->Length
  1330. );
  1331. if (deviceExtension->InterfaceInfo)
  1332. {
  1333. ULONG pipeIndex;
  1334. ULONG numPipes;
  1335. RtlCopyMemory(
  1336. deviceExtension->InterfaceInfo,
  1337. interfaceInfo,
  1338. interfaceInfo->Length
  1339. );
  1340. // Initialize the PipeList array pointers back into the
  1341. // InterfaceInfo.
  1342. //
  1343. numPipes = deviceExtension->InterfaceInfo->NumberOfPipes;
  1344. for (pipeIndex = 0; pipeIndex < numPipes; pipeIndex++)
  1345. {
  1346. deviceExtension->PipeList[pipeIndex].PipeIndex =
  1347. (UCHAR)pipeIndex;
  1348. deviceExtension->PipeList[pipeIndex].PipeInfo =
  1349. &deviceExtension->InterfaceInfo->Pipes[pipeIndex];
  1350. }
  1351. }
  1352. else
  1353. {
  1354. // Could not allocate a copy of interface information
  1355. //
  1356. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1357. }
  1358. }
  1359. // Done with the URB
  1360. //
  1361. ExFreePool(urb);
  1362. }
  1363. else
  1364. {
  1365. // Could not allocate urb
  1366. //
  1367. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1368. }
  1369. }
  1370. else
  1371. {
  1372. // Did not parse an Interface Descriptor out of the Configuration
  1373. // Descriptor, the Configuration Descriptor must be bad.
  1374. //
  1375. ntStatus = STATUS_UNSUCCESSFUL;
  1376. }
  1377. // Done with the interface list
  1378. //
  1379. ExFreePool(interfaceList);
  1380. }
  1381. else
  1382. {
  1383. // Could not allocate Interface List
  1384. //
  1385. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1386. }
  1387. DBGPRINT(2, ("exit: I82930_SelectConfiguration %08X\n", ntStatus));
  1388. LOGENTRY('scon', ntStatus, 0, 0);
  1389. return ntStatus;
  1390. }
  1391. //******************************************************************************
  1392. //
  1393. // I82930_UnConfigure()
  1394. //
  1395. // Must be called at IRQL <= DISPATCH_LEVEL
  1396. //
  1397. //******************************************************************************
  1398. NTSTATUS
  1399. I82930_UnConfigure (
  1400. IN PDEVICE_OBJECT DeviceObject
  1401. )
  1402. {
  1403. PDEVICE_EXTENSION deviceExtension;
  1404. NTSTATUS ntStatus;
  1405. PURB urb;
  1406. ULONG ulSize;
  1407. DBGPRINT(2, ("enter: I82930_UnConfigure\n"));
  1408. LOGENTRY('UCON', DeviceObject, 0, 0);
  1409. deviceExtension = DeviceObject->DeviceExtension;
  1410. // Allocate a URB for the SELECT_CONFIGURATION request. As we are
  1411. // unconfiguring the device, the request needs no pipe and interface
  1412. // information structures.
  1413. //
  1414. ulSize = sizeof(struct _URB_SELECT_CONFIGURATION) -
  1415. sizeof(USBD_INTERFACE_INFORMATION);
  1416. urb = ExAllocatePool(
  1417. NonPagedPool,
  1418. ulSize
  1419. );
  1420. if (urb)
  1421. {
  1422. // Initialize the URB. A NULL Configuration Descriptor indicates
  1423. // that the device should be unconfigured.
  1424. //
  1425. UsbBuildSelectConfigurationRequest(
  1426. urb,
  1427. (USHORT)ulSize,
  1428. NULL
  1429. );
  1430. // Now issue the USB request to set the Configuration
  1431. //
  1432. ntStatus = I82930_SyncSendUsbRequest(DeviceObject,
  1433. urb);
  1434. // Done with the URB now.
  1435. //
  1436. ExFreePool(urb);
  1437. // The device is no longer configured.
  1438. //
  1439. deviceExtension->ConfigurationHandle = 0;
  1440. if (deviceExtension->InterfaceInfo != NULL)
  1441. {
  1442. ExFreePool(deviceExtension->InterfaceInfo);
  1443. deviceExtension->InterfaceInfo = NULL;
  1444. }
  1445. }
  1446. else
  1447. {
  1448. // Could not allocate the URB.
  1449. //
  1450. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1451. }
  1452. DBGPRINT(2, ("exit: I82930_UnConfigure %08X\n", ntStatus));
  1453. LOGENTRY('ucon', ntStatus, 0, 0);
  1454. return ntStatus;
  1455. }
  1456. //******************************************************************************
  1457. //
  1458. // I82930_SelectAlternateInterface()
  1459. //
  1460. // Must be called at IRQL <= DISPATCH_LEVEL
  1461. //
  1462. //******************************************************************************
  1463. NTSTATUS
  1464. I82930_SelectAlternateInterface (
  1465. IN PDEVICE_OBJECT DeviceObject,
  1466. IN UCHAR AlternateSetting
  1467. )
  1468. {
  1469. NTSTATUS ntStatus;
  1470. USHORT urbSize;
  1471. PURB urb;
  1472. ULONG i;
  1473. PDEVICE_EXTENSION deviceExtension;
  1474. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  1475. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  1476. PUSBD_INTERFACE_INFORMATION interfaceInfo;
  1477. DBGPRINT(2, ("enter: I82930_SelectAlternateInterface\n"));
  1478. LOGENTRY('SALT', DeviceObject, 0, 0);
  1479. deviceExtension = DeviceObject->DeviceExtension;
  1480. configurationDescriptor = deviceExtension->ConfigurationDescriptor;
  1481. interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
  1482. configurationDescriptor,
  1483. configurationDescriptor,
  1484. -1, // InterfaceNumber, don't care
  1485. AlternateSetting,
  1486. -1, // InterfaceClass, don't care
  1487. -1, // InterfaceSubClass, don't care
  1488. -1 // InterfaceProtocol, don't care
  1489. );
  1490. if (interfaceDescriptor != NULL)
  1491. {
  1492. urbSize = GET_SELECT_INTERFACE_REQUEST_SIZE(interfaceDescriptor->bNumEndpoints);
  1493. urb = ExAllocatePoolWithTag(NonPagedPool,
  1494. urbSize,
  1495. POOL_TAG);
  1496. if (urb != NULL)
  1497. {
  1498. RtlZeroMemory(urb, urbSize);
  1499. urb->UrbHeader.Length = urbSize;
  1500. urb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE;
  1501. urb->UrbSelectInterface.ConfigurationHandle =
  1502. deviceExtension->ConfigurationHandle;
  1503. interfaceInfo = &urb->UrbSelectInterface.Interface;
  1504. interfaceInfo->Length = GET_USBD_INTERFACE_SIZE(interfaceDescriptor->bNumEndpoints);
  1505. interfaceInfo->InterfaceNumber = interfaceDescriptor->bInterfaceNumber;
  1506. interfaceInfo->AlternateSetting = AlternateSetting;
  1507. for (i = 0; i < interfaceDescriptor->bNumEndpoints; i++)
  1508. {
  1509. interfaceInfo->Pipes[i].MaximumTransferSize = 0x10000;
  1510. }
  1511. // Now issue the USB request to select the alternate interface
  1512. //
  1513. ntStatus = I82930_SyncSendUsbRequest(DeviceObject,
  1514. urb);
  1515. if (NT_SUCCESS(ntStatus))
  1516. {
  1517. if (deviceExtension->InterfaceInfo != NULL)
  1518. {
  1519. ExFreePool(deviceExtension->InterfaceInfo);
  1520. deviceExtension->InterfaceInfo = NULL;
  1521. }
  1522. // Save a copy of the interface information returned
  1523. // by the SELECT_INTERFACE request in the Device
  1524. // Extension. This gives us a list of PIPE_INFORMATION
  1525. // structures for each pipe opened in this configuration.
  1526. //
  1527. deviceExtension->InterfaceInfo = ExAllocatePool(
  1528. PagedPool,
  1529. interfaceInfo->Length
  1530. );
  1531. if (deviceExtension->InterfaceInfo)
  1532. {
  1533. ULONG pipeIndex;
  1534. ULONG numPipes;
  1535. RtlCopyMemory(deviceExtension->InterfaceInfo,
  1536. interfaceInfo,
  1537. interfaceInfo->Length
  1538. );
  1539. // Initialize the PipeList array pointers back into the
  1540. // InterfaceInfo.
  1541. //
  1542. numPipes = deviceExtension->InterfaceInfo->NumberOfPipes;
  1543. for (pipeIndex = 0; pipeIndex < numPipes; pipeIndex++)
  1544. {
  1545. deviceExtension->PipeList[pipeIndex].PipeIndex =
  1546. (UCHAR)pipeIndex;
  1547. deviceExtension->PipeList[pipeIndex].PipeInfo =
  1548. &deviceExtension->InterfaceInfo->Pipes[pipeIndex];
  1549. }
  1550. }
  1551. else
  1552. {
  1553. // Could not allocate a copy of interface information
  1554. //
  1555. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1556. }
  1557. }
  1558. // Done with the URB
  1559. //
  1560. ExFreePool(urb);
  1561. }
  1562. else
  1563. {
  1564. // Could not allocate urb
  1565. //
  1566. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1567. }
  1568. }
  1569. else
  1570. {
  1571. // Bad AlternateSetting
  1572. //
  1573. ntStatus = STATUS_INVALID_PARAMETER;
  1574. }
  1575. DBGPRINT(2, ("exit: I82930_SelectAlternateInterface %08X\n", ntStatus));
  1576. LOGENTRY('salt', ntStatus, 0, 0);
  1577. return ntStatus;
  1578. }