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.

6201 lines
167 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. SERVICE.C
  5. Abstract:
  6. Services exported by USBD
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. 09-29-95 : created
  12. --*/
  13. #include "wdm.h"
  14. #include <windef.h>
  15. #include <unknown.h>
  16. #ifdef DRM_SUPPORT
  17. #include <ks.h>
  18. #include <ksmedia.h>
  19. #include <drmk.h>
  20. #include <ksdrmhlp.h>
  21. #endif
  22. #include "stdarg.h"
  23. #include "stdio.h"
  24. #include <initguid.h>
  25. #include <wdmguid.h>
  26. #include "usbdi.h" //public data structures
  27. #include "hcdi.h"
  28. #include "usbd.h" //private data strutures
  29. #include "usbdlib.h"
  30. #define USBD
  31. #include "usbdlibi.h"
  32. #undef USBD
  33. NTSTATUS
  34. DllUnload(
  35. VOID
  36. );
  37. NTSTATUS
  38. DllInitialize(
  39. PUNICODE_STRING RegistryPath
  40. );
  41. NTSTATUS
  42. USBD_GetDeviceInformation(
  43. IN PUSB_NODE_CONNECTION_INFORMATION DeviceInformation,
  44. IN ULONG DeviceInformationLength,
  45. IN PUSBD_DEVICE_DATA DeviceData
  46. );
  47. ULONG
  48. USBD_AllocateDeviceName(
  49. PUNICODE_STRING DeviceNameUnicodeString
  50. );
  51. VOID
  52. USBD_FreeDeviceName(
  53. ULONG DeviceNameHandle
  54. );
  55. NTSTATUS
  56. USBD_RegisterHostController(
  57. IN PDEVICE_OBJECT PnPBusDeviceObject,
  58. IN PDEVICE_OBJECT HcdDeviceObject,
  59. IN PDEVICE_OBJECT HcdTopOfStackDeviceObject,
  60. IN PDRIVER_OBJECT HcdDriverObject,
  61. IN HCD_DEFFERED_START_FUNCTION *HcdDeferredStartDevice,
  62. IN HCD_SET_DEVICE_POWER_STATE *HcdSetDevicePowerState,
  63. IN HCD_GET_CURRENT_FRAME *HcdGetCurrentFrame,
  64. IN HCD_GET_CONSUMED_BW *HcdGetConsumedBW,
  65. IN HCD_SUBMIT_ISO_URB *HcdSubmitIsoUrb,
  66. // this parameter is only needed until we resolve device naming
  67. // issues with PNP
  68. IN ULONG HcdDeviceNameHandle
  69. );
  70. NTSTATUS
  71. USBD_InitializeDevice(
  72. IN PUSBD_DEVICE_DATA DeviceData,
  73. IN PDEVICE_OBJECT DeviceObject,
  74. IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
  75. IN ULONG DeviceDescriptorLength,
  76. IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
  77. IN ULONG ConfigDescriptorLength
  78. );
  79. NTSTATUS
  80. USBD_RemoveDevice(
  81. IN PUSBD_DEVICE_DATA DeviceData,
  82. IN PDEVICE_OBJECT DeviceObject,
  83. IN UCHAR Flags
  84. );
  85. PURB
  86. USBD_CreateConfigurationRequestEx(
  87. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  88. IN PUSBD_INTERFACE_LIST_ENTRY InterfaceList
  89. );
  90. PUSB_INTERFACE_DESCRIPTOR
  91. USBD_ParseConfigurationDescriptorEx(
  92. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  93. IN PVOID StartPosition,
  94. IN LONG InterfaceNumber,
  95. IN LONG AlternateSetting,
  96. IN LONG InterfaceClass,
  97. IN LONG InterfaceSubClass,
  98. IN LONG InterfaceProtocol
  99. );
  100. VOID
  101. USBD_WaitDeviceMutex(
  102. PDEVICE_OBJECT RootHubPDO
  103. );
  104. VOID
  105. USBD_FreeDeviceMutex(
  106. PDEVICE_OBJECT RootHubPDO
  107. );
  108. PUSB_COMMON_DESCRIPTOR
  109. USBD_ParseDescriptors(
  110. IN PVOID DescriptorBuffer,
  111. IN ULONG TotalLength,
  112. IN PVOID StartPosition,
  113. IN LONG DescriptorType
  114. );
  115. PUSB_INTERFACE_DESCRIPTOR
  116. USBD_ParseConfigurationDescriptor(
  117. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  118. IN UCHAR InterfaceNumber,
  119. IN UCHAR AlternateSetting
  120. );
  121. PURB
  122. USBD_CreateConfigurationRequest(
  123. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  124. IN OUT PUSHORT Siz
  125. );
  126. NTSTATUS
  127. USBD_GetDeviceName(
  128. IN PDEVICE_OBJECT DeviceObject,
  129. IN OUT PUNICODE_STRING DeviceNameUnicodeString
  130. );
  131. VOID
  132. USBD_RhDelayedSetPowerD0Worker(
  133. IN PVOID Context);
  134. PWCHAR
  135. GetString(PWCHAR pwc, BOOLEAN MultiSZ);
  136. NTSTATUS
  137. USBD_GetBusInterface(
  138. IN PDEVICE_OBJECT RootHubPdo,
  139. IN PIRP Irp
  140. );
  141. #ifdef PAGE_CODE
  142. #ifdef ALLOC_PRAGMA
  143. #pragma alloc_text(PAGE, DllUnload)
  144. #pragma alloc_text(PAGE, DllInitialize)
  145. #pragma alloc_text(PAGE, USBD_GetDeviceInformation)
  146. #pragma alloc_text(PAGE, USBD_AllocateDeviceName)
  147. #pragma alloc_text(PAGE, USBD_GetDeviceName)
  148. #pragma alloc_text(PAGE, GetString)
  149. #pragma alloc_text(PAGE, USBD_FreeDeviceName)
  150. #pragma alloc_text(PAGE, USBD_RegisterHostController)
  151. #pragma alloc_text(PAGE, USBD_CreateDevice)
  152. #pragma alloc_text(PAGE, USBD_RemoveDevice)
  153. #pragma alloc_text(PAGE, USBD_InitializeDevice)
  154. #pragma alloc_text(PAGE, USBD_CreateConfigurationRequestEx)
  155. #pragma alloc_text(PAGE, USBD_ParseDescriptors)
  156. #pragma alloc_text(PAGE, USBD_ParseConfigurationDescriptorEx)
  157. #pragma alloc_text(PAGE, USBD_ParseConfigurationDescriptor)
  158. #pragma alloc_text(PAGE, USBD_CreateConfigurationRequest)
  159. #pragma alloc_text(PAGE, USBD_WaitDeviceMutex)
  160. #pragma alloc_text(PAGE, USBD_FreeDeviceMutex)
  161. #pragma alloc_text(PAGE, USBD_InternalGetInterfaceLength)
  162. #pragma alloc_text(PAGE, USBD_RhDelayedSetPowerD0Worker)
  163. #ifdef DRM_SUPPORT
  164. #pragma alloc_text(PAGE, USBD_FdoSetContentId)
  165. #endif
  166. #endif
  167. #endif
  168. /*
  169. ********************************************************************************
  170. * DllUnload
  171. ********************************************************************************
  172. *
  173. * We need this routine so that the driver can get unloaded when all
  174. * references have been dropped by the minidriver.
  175. *
  176. */
  177. NTSTATUS
  178. DllUnload (VOID)
  179. {
  180. PAGED_CODE();
  181. USBD_KdPrint(1, (" DllUnload\n"));
  182. return STATUS_SUCCESS;
  183. }
  184. /*
  185. ********************************************************************************
  186. * DllInitialize
  187. ********************************************************************************
  188. *
  189. * This routine called instead of DriverEntry since we're loaded as a DLL.
  190. *
  191. */
  192. NTSTATUS
  193. DllInitialize (PUNICODE_STRING RegistryPath)
  194. {
  195. PAGED_CODE();
  196. USBD_KdPrint(1, (" DllInitialize\n"));
  197. return STATUS_SUCCESS;
  198. }
  199. ULONG
  200. USBD_CalculateUsbBandwidth(
  201. ULONG MaxPacketSize,
  202. UCHAR EndpointType,
  203. BOOLEAN LowSpeed
  204. )
  205. /*++
  206. Routine Description:
  207. Arguments:
  208. Return Value:
  209. banwidth consumed in bits/ms, returns 0 for bulk
  210. and control endpoints
  211. --*/
  212. {
  213. ULONG bw;
  214. //
  215. // control, iso, bulk, interrupt
  216. //
  217. ULONG overhead[4] = {
  218. 0,
  219. USB_ISO_OVERHEAD_BYTES,
  220. 0,
  221. USB_INTERRUPT_OVERHEAD_BYTES
  222. };
  223. USBD_ASSERT(EndpointType<4);
  224. //
  225. // Calculate bandwidth for endpoint. We will use the
  226. // approximation: (overhead bytes plus MaxPacket bytes)
  227. // times 8 bits/byte times worst case bitstuffing overhead.
  228. // This gives bit times, for low speed endpoints we multiply
  229. // by 8 again to convert to full speed bits.
  230. //
  231. //
  232. // Figure out how many bits are required for the transfer.
  233. // (multiply by 7/6 because, in the worst case you might
  234. // have a bit-stuff every six bits requiring 7 bit times to
  235. // transmit 6 bits of data.)
  236. //
  237. // overhead(bytes) * maxpacket(bytes/ms) * 8
  238. // (bits/byte) * bitstuff(7/6) = bits/ms
  239. bw = ((overhead[EndpointType]+MaxPacketSize) * 8 * 7) / 6;
  240. // return zero for control or bulk
  241. if (!overhead[EndpointType]) {
  242. bw = 0;
  243. }
  244. if (LowSpeed) {
  245. bw *= 8;
  246. }
  247. return bw;
  248. }
  249. //
  250. // These APIS replace USBD_CreateConfigurationRequest,
  251. // USBD_ParseConfigurationDescriptor
  252. PURB
  253. USBD_CreateConfigurationRequestEx(
  254. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  255. IN PUSBD_INTERFACE_LIST_ENTRY InterfaceList
  256. )
  257. /*++
  258. Routine Description:
  259. Arguments:
  260. Return Value:
  261. Pointer to initailized select_configuration urb.
  262. --*/
  263. {
  264. PURB urb = NULL;
  265. ULONG numInterfaces, numPipes;
  266. PUSBD_INTERFACE_LIST_ENTRY interfaceList;
  267. USHORT siz;
  268. PAGED_CODE();
  269. //
  270. // Our mission here is to construct a URB of the proper
  271. // size and format for a select_configuration request.
  272. //
  273. // This function uses the configurstion descritor as a
  274. // reference and builds a URB with interface_information
  275. // structures for each interface requested in the interface
  276. // list passed in
  277. //
  278. // NOTE: the config descriptor may contain interfaces that
  279. // the caller does not specify in the list -- in this case
  280. // the other interfaces will be ignored.
  281. //
  282. USBD_KdPrint(3, ("'USBD_CreateConfigurationRequestEx list = %x\n",
  283. InterfaceList));
  284. //
  285. // first figure out how many interfaces we are dealing with
  286. //
  287. interfaceList = InterfaceList;
  288. numInterfaces = 0;
  289. numPipes = 0;
  290. while (interfaceList->InterfaceDescriptor) {
  291. numInterfaces++;
  292. numPipes+=interfaceList->InterfaceDescriptor->bNumEndpoints;
  293. interfaceList++;
  294. }
  295. siz = (USHORT) GET_SELECT_CONFIGURATION_REQUEST_SIZE(numInterfaces,
  296. numPipes);
  297. urb = ExAllocatePoolWithTag(NonPagedPool, siz, USBD_TAG);
  298. if (urb) {
  299. PUSBD_INTERFACE_INFORMATION iface;
  300. //
  301. // now all we have to do is initialize the urb
  302. //
  303. RtlZeroMemory(urb, siz);
  304. iface = &urb->UrbSelectConfiguration.Interface;
  305. interfaceList = InterfaceList;
  306. while (interfaceList->InterfaceDescriptor) {
  307. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor =
  308. interfaceList->InterfaceDescriptor;
  309. LONG j;
  310. iface->InterfaceNumber =
  311. interfaceDescriptor->bInterfaceNumber;
  312. iface->AlternateSetting =
  313. interfaceDescriptor->bAlternateSetting;
  314. iface->NumberOfPipes =
  315. interfaceDescriptor->bNumEndpoints;
  316. for (j=0; j<interfaceDescriptor->bNumEndpoints; j++) {
  317. iface->Pipes[j].MaximumTransferSize =
  318. USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
  319. iface->Pipes[j].PipeFlags = 0;
  320. }
  321. iface->Length =
  322. (USHORT) GET_USBD_INTERFACE_SIZE(
  323. interfaceDescriptor->bNumEndpoints);
  324. USBD_ASSERT(((PUCHAR) iface) + iface->Length <=
  325. ((PUCHAR) urb) + siz);
  326. interfaceList->Interface = iface;
  327. interfaceList++;
  328. iface = (PUSBD_INTERFACE_INFORMATION) ((PUCHAR) iface +
  329. iface->Length);
  330. USBD_KdPrint(3, ("'next interface = %x\n", iface));
  331. }
  332. urb->UrbHeader.Length = siz;
  333. urb->UrbHeader.Function = URB_FUNCTION_SELECT_CONFIGURATION;
  334. urb->UrbSelectConfiguration.ConfigurationDescriptor =
  335. ConfigurationDescriptor;
  336. }
  337. #if DBG
  338. interfaceList = InterfaceList;
  339. while (interfaceList->InterfaceDescriptor) {
  340. USBD_KdPrint(3, ("'InterfaceList, Interface = %x\n",
  341. interfaceList->Interface));
  342. USBD_KdPrint(3, ("'InterfaceList, InterfaceDescriptor = %x\n",
  343. interfaceList->InterfaceDescriptor));
  344. interfaceList++;
  345. }
  346. USBD_KdPrint(3, ("'urb = %x\n", urb));
  347. #endif
  348. return urb;
  349. }
  350. PUSB_COMMON_DESCRIPTOR
  351. USBD_ParseDescriptors(
  352. IN PVOID DescriptorBuffer,
  353. IN ULONG TotalLength,
  354. IN PVOID StartPosition,
  355. IN LONG DescriptorType
  356. )
  357. /*++
  358. Routine Description:
  359. Parses a group of standard USB configuration descriptors (returned
  360. from a device) for a specific descriptor type.
  361. Arguments:
  362. DescriptorBuffer - pointer to a block of contiguous USB desscriptors
  363. TotalLength - size in bytes of the Descriptor buffer
  364. StartPosition - starting position in the buffer to begin parsing,
  365. this must point to the begining of a USB descriptor.
  366. DescriptorType - USB descritor type to locate.
  367. Return Value:
  368. pointer to a usb descriptor with a DescriptorType field matching the
  369. input parameter or NULL if not found.
  370. --*/
  371. {
  372. PUCHAR pch = (PUCHAR) StartPosition, end;
  373. PUSB_COMMON_DESCRIPTOR usbDescriptor, foundUsbDescriptor = NULL;
  374. PAGED_CODE();
  375. end = ((PUCHAR) (DescriptorBuffer)) + TotalLength;
  376. while (pch < end) {
  377. // see if we are pointing at an interface
  378. // if not skip over the other junk
  379. usbDescriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  380. if (usbDescriptor->bDescriptorType ==
  381. DescriptorType) {
  382. foundUsbDescriptor = usbDescriptor;
  383. break;
  384. }
  385. // note we still stop in debug because the
  386. // device passed us bad data, the following
  387. // test will prevent us from hanging
  388. if (usbDescriptor->bLength == 0) {
  389. USBD_KdTrap((
  390. "USB driver passed in bad data!\n-->you have a broken device or driver\n-->hit g to cointinue\n"));
  391. break;
  392. }
  393. pch += usbDescriptor->bLength;
  394. }
  395. USBD_KdPrint(3, ("'USBD_ParseDescriptors %x\n", foundUsbDescriptor));
  396. return foundUsbDescriptor;
  397. }
  398. PUSB_INTERFACE_DESCRIPTOR
  399. USBD_ParseConfigurationDescriptorEx(
  400. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  401. IN PVOID StartPosition,
  402. IN LONG InterfaceNumber,
  403. IN LONG AlternateSetting,
  404. IN LONG InterfaceClass,
  405. IN LONG InterfaceSubClass,
  406. IN LONG InterfaceProtocol
  407. )
  408. /*++
  409. Routine Description:
  410. Parses a standard USB configuration descriptor (returned from a device)
  411. for a specific interface, alternate setting class subclass or protocol
  412. codes
  413. Arguments:
  414. ConfigurationDescriptor -
  415. StartPosition -
  416. InterfaceNumber -
  417. AlternateSetting
  418. InterfaceClass -
  419. InterfaceSubClass -
  420. InterfaceProtocol -
  421. Return Value:
  422. NT status code.
  423. --*/
  424. {
  425. PUSB_INTERFACE_DESCRIPTOR foundInterfaceDescriptor = NULL;
  426. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  427. PAGED_CODE();
  428. USBD_KdPrint(3, ("'USBD_ParseConfigurationDescriptorEx\n"));
  429. ASSERT(ConfigurationDescriptor->bDescriptorType
  430. == USB_CONFIGURATION_DESCRIPTOR_TYPE);
  431. //
  432. // we walk the table of descriptors looking for an
  433. // interface descriptor with parameters matching those
  434. // passed in.
  435. //
  436. do {
  437. //
  438. // Search for descriptor type 'interface'
  439. //
  440. interfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)
  441. USBD_ParseDescriptors(ConfigurationDescriptor,
  442. ConfigurationDescriptor->wTotalLength,
  443. StartPosition,
  444. USB_INTERFACE_DESCRIPTOR_TYPE);
  445. //
  446. // do we have a match?
  447. //
  448. if (interfaceDescriptor != NULL) {
  449. foundInterfaceDescriptor =
  450. interfaceDescriptor;
  451. if (InterfaceNumber != -1 &&
  452. interfaceDescriptor->bInterfaceNumber != InterfaceNumber) {
  453. foundInterfaceDescriptor = NULL;
  454. }
  455. if (AlternateSetting != -1 &&
  456. interfaceDescriptor->bAlternateSetting != AlternateSetting) {
  457. foundInterfaceDescriptor = NULL;
  458. }
  459. if (InterfaceClass != -1 &&
  460. interfaceDescriptor->bInterfaceClass != InterfaceClass) {
  461. foundInterfaceDescriptor = NULL;
  462. }
  463. if (InterfaceSubClass != -1 &&
  464. interfaceDescriptor->bInterfaceSubClass !=
  465. InterfaceSubClass) {
  466. foundInterfaceDescriptor = NULL;
  467. }
  468. if (InterfaceProtocol != -1 &&
  469. interfaceDescriptor->bInterfaceProtocol !=
  470. InterfaceProtocol) {
  471. foundInterfaceDescriptor = NULL;
  472. }
  473. StartPosition =
  474. ((PUCHAR)interfaceDescriptor) + interfaceDescriptor->bLength;
  475. }
  476. if (foundInterfaceDescriptor) {
  477. break;
  478. }
  479. } while (interfaceDescriptor != NULL);
  480. return (foundInterfaceDescriptor);
  481. }
  482. PUSB_INTERFACE_DESCRIPTOR
  483. USBD_ParseConfigurationDescriptor(
  484. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  485. IN UCHAR InterfaceNumber,
  486. IN UCHAR AlternateSetting
  487. )
  488. /*++
  489. Routine Description:
  490. Arguments:
  491. Return Value:
  492. interface descriptor or NULL.
  493. --*/
  494. {
  495. PAGED_CODE();
  496. return USBD_ParseConfigurationDescriptorEx(
  497. ConfigurationDescriptor,
  498. ConfigurationDescriptor,
  499. InterfaceNumber,
  500. AlternateSetting,
  501. -1,
  502. -1,
  503. -1);
  504. }
  505. PURB
  506. USBD_CreateConfigurationRequest(
  507. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  508. IN OUT PUSHORT Siz
  509. )
  510. /*++
  511. Routine Description:
  512. Arguments:
  513. Return Value:
  514. Pointer to initailized select_configuration urb.
  515. --*/
  516. {
  517. PURB urb = NULL;
  518. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  519. PUSBD_INTERFACE_LIST_ENTRY interfaceList, tmp;
  520. LONG numberOfInterfaces, interfaceNumber, i;
  521. PAGED_CODE();
  522. USBD_KdPrint(3, ("' enter USBD_CreateConfigurationRequest cd = %x\n",
  523. ConfigurationDescriptor));
  524. //
  525. // build a request structure and call the new api
  526. //
  527. numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  528. tmp = interfaceList =
  529. ExAllocatePoolWithTag(PagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) *
  530. (numberOfInterfaces+1), USBD_TAG);
  531. //
  532. // just grab the first alt setting we find for each interface
  533. //
  534. i = interfaceNumber = 0;
  535. while (i< numberOfInterfaces) {
  536. interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
  537. ConfigurationDescriptor,
  538. ConfigurationDescriptor,
  539. interfaceNumber,
  540. 0, // assume alt setting zero here
  541. -1,
  542. -1,
  543. -1);
  544. USBD_ASSERT(interfaceDescriptor != NULL);
  545. if (interfaceDescriptor) {
  546. interfaceList->InterfaceDescriptor =
  547. interfaceDescriptor;
  548. interfaceList++;
  549. i++;
  550. } else {
  551. // could not find the requested interface descriptor
  552. // bail, we will prorblay crash somewhere in the
  553. // client driver.
  554. goto USBD_CreateConfigurationRequest_Done;
  555. }
  556. interfaceNumber++;
  557. }
  558. //
  559. // terminate the list
  560. //
  561. interfaceList->InterfaceDescriptor = NULL;
  562. urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor,
  563. tmp);
  564. USBD_CreateConfigurationRequest_Done:
  565. ExFreePool(tmp);
  566. if (urb) {
  567. *Siz = urb->UrbHeader.Length;
  568. }
  569. return urb;
  570. }
  571. ULONG
  572. USBD_InternalGetInterfaceLength(
  573. IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
  574. IN PUCHAR End
  575. )
  576. /*++
  577. Routine Description:
  578. Initialize the configuration handle structure.
  579. Arguments:
  580. InterfaceDescriptor - pointer to usb interface descriptor
  581. followed by endpoint descriptors
  582. Return Value:
  583. Length of the interface plus endpoint descriptors and class specific
  584. descriptors in bytes.
  585. --*/
  586. {
  587. PUCHAR pch = (PUCHAR) InterfaceDescriptor;
  588. ULONG i, numEndpoints;
  589. PUSB_ENDPOINT_DESCRIPTOR endpointDescriptor;
  590. PUSB_COMMON_DESCRIPTOR usbDescriptor;
  591. PAGED_CODE();
  592. ASSERT(InterfaceDescriptor->bDescriptorType ==
  593. USB_INTERFACE_DESCRIPTOR_TYPE);
  594. i = InterfaceDescriptor->bLength;
  595. numEndpoints = InterfaceDescriptor->bNumEndpoints;
  596. // advance to the first endpoint
  597. pch += i;
  598. while (numEndpoints) {
  599. usbDescriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  600. while (usbDescriptor->bDescriptorType !=
  601. USB_ENDPOINT_DESCRIPTOR_TYPE) {
  602. i += usbDescriptor->bLength;
  603. pch += usbDescriptor->bLength;
  604. usbDescriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  605. if (pch >= End || usbDescriptor->bLength == 0) {
  606. USBD_Warning(NULL,
  607. "Bad USB descriptors in USBD_InternalGetInterfaceLength, fail.\n",
  608. FALSE);
  609. // If descriptors are bad, don't index past the end of the
  610. // buffer. Return 0 as the interface length and the caller
  611. // should then be able to handle this appropriately.
  612. i = 0;
  613. goto GetInterfaceLength_exit;
  614. }
  615. }
  616. endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) pch;
  617. ASSERT(endpointDescriptor->bDescriptorType ==
  618. USB_ENDPOINT_DESCRIPTOR_TYPE);
  619. i += endpointDescriptor->bLength;
  620. pch += endpointDescriptor->bLength;
  621. numEndpoints--;
  622. }
  623. while (pch < End) {
  624. // see if we are pointing at an interface
  625. // if not skip over the other junk
  626. usbDescriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  627. if (usbDescriptor->bDescriptorType ==
  628. USB_INTERFACE_DESCRIPTOR_TYPE) {
  629. break;
  630. }
  631. USBD_ASSERT(usbDescriptor->bLength != 0);
  632. i += usbDescriptor->bLength;
  633. pch += usbDescriptor->bLength;
  634. }
  635. GetInterfaceLength_exit:
  636. USBD_KdPrint(3, ("'USBD_GetInterfaceLength %x\n", i));
  637. return i;
  638. }
  639. ULONG
  640. USBD_GetInterfaceLength(
  641. IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
  642. IN PUCHAR BufferEnd
  643. )
  644. /*++
  645. Routine Description:
  646. Arguments:
  647. Return Value:
  648. --*/
  649. {
  650. return USBD_InternalGetInterfaceLength(InterfaceDescriptor, BufferEnd);
  651. }
  652. NTSTATUS
  653. USBD_GetPdoRegistryParameter(
  654. IN PDEVICE_OBJECT PhysicalDeviceObject,
  655. IN OUT PVOID Parameter,
  656. IN ULONG ParameterLength,
  657. IN PWCHAR KeyName,
  658. IN ULONG KeyNameLength
  659. )
  660. /*++
  661. Routine Description:
  662. Arguments:
  663. Return Value:
  664. --*/
  665. {
  666. NTSTATUS ntStatus;
  667. HANDLE handle;
  668. PAGED_CODE();
  669. ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  670. PLUGPLAY_REGKEY_DRIVER,
  671. STANDARD_RIGHTS_ALL,
  672. &handle);
  673. if (NT_SUCCESS(ntStatus)) {
  674. ntStatus = USBD_GetRegistryKeyValue(handle,
  675. KeyName,
  676. KeyNameLength,
  677. Parameter,
  678. ParameterLength);
  679. ZwClose(handle);
  680. }
  681. return ntStatus;
  682. }
  683. VOID
  684. USBD_GetUSBDIVersion(
  685. PUSBD_VERSION_INFORMATION VersionInformation
  686. )
  687. {
  688. if (VersionInformation != NULL) {
  689. VersionInformation->USBDI_Version = USBDI_VERSION;
  690. VersionInformation->Supported_USB_Version = 0x100;
  691. }
  692. }
  693. #ifdef USBD_DRIVER // USBPORT supercedes most of USBD, so we will remove
  694. // the obsolete code by compiling it only if
  695. // USBD_DRIVER is set.
  696. //#if DBG
  697. //VOID
  698. //USBD_IoCompleteRequest(
  699. // IN PIRP Irp,
  700. // IN CCHAR PriorityBoost
  701. // )
  702. //{
  703. // KIRQL irql;
  704. // KeRaiseIrql(DISPATCH_LEVEL, &irql);
  705. // IoCompleteRequest(Irp, PriorityBoost);
  706. // KeLowerIrql(irql);
  707. //}
  708. //#endif
  709. // this code is here to support the old API
  710. // once we eliminate this service it can be removed
  711. NTSTATUS
  712. USBD_GetDeviceInformationX(
  713. IN PUSB_NODE_CONNECTION_INFORMATION DeviceInformation,
  714. IN ULONG DeviceInformationLength,
  715. IN PUSBD_DEVICE_DATA DeviceData
  716. )
  717. /*++
  718. Routine Description:
  719. Returns information about a device given the handle
  720. Arguments:
  721. Return Value:
  722. NT status code
  723. --*/
  724. {
  725. ULONG need;
  726. NTSTATUS ntStatus = STATUS_SUCCESS;
  727. PUSBD_CONFIG configHandle;
  728. ULONG i,j,k;
  729. PAGED_CODE();
  730. DeviceInformation->DeviceAddress = DeviceData->DeviceAddress;
  731. DeviceInformation->LowSpeed = DeviceData->LowSpeed;
  732. configHandle = DeviceData->ConfigurationHandle;
  733. DeviceInformation->NumberOfOpenPipes = 0;
  734. DeviceInformation->CurrentConfigurationValue = 0;
  735. // get the pipe information
  736. if (configHandle) {
  737. DeviceInformation->CurrentConfigurationValue =
  738. configHandle->ConfigurationDescriptor->bConfigurationValue;
  739. for (i=0;
  740. i< configHandle->ConfigurationDescriptor->bNumInterfaces;
  741. i++) {
  742. DeviceInformation->NumberOfOpenPipes +=
  743. configHandle->InterfaceHandle[i]->
  744. InterfaceInformation->NumberOfPipes;
  745. }
  746. need = DeviceInformation->NumberOfOpenPipes * sizeof(USB_PIPE_INFO) +
  747. sizeof(USB_NODE_CONNECTION_INFORMATION);
  748. if (need > DeviceInformationLength) {
  749. ntStatus = STATUS_BUFFER_TOO_SMALL;
  750. } else {
  751. j=0;
  752. for (i=0;
  753. i<configHandle->ConfigurationDescriptor->bNumInterfaces;
  754. i++) {
  755. PUSBD_INTERFACE interfaceHandle =
  756. configHandle->InterfaceHandle[i];
  757. for (k=0;
  758. k<interfaceHandle->InterfaceInformation->NumberOfPipes;
  759. k++, j++) {
  760. DeviceInformation->PipeList[j].ScheduleOffset =
  761. interfaceHandle->PipeHandle[k].ScheduleOffset;
  762. RtlCopyMemory(&DeviceInformation->PipeList[j].
  763. EndpointDescriptor,
  764. &interfaceHandle->PipeHandle[k].
  765. EndpointDescriptor,
  766. sizeof(USB_ENDPOINT_DESCRIPTOR));
  767. }
  768. }
  769. }
  770. }
  771. return ntStatus;
  772. }
  773. NTSTATUS
  774. USBD_GetDeviceInformation(
  775. IN PUSB_NODE_CONNECTION_INFORMATION DeviceInformation,
  776. IN ULONG DeviceInformationLength,
  777. IN PUSBD_DEVICE_DATA DeviceData
  778. )
  779. {
  780. USBD_KdPrint(0,
  781. (" WARNING: Driver using obsolete service enrty point (USBD_GetDeviceInformation) - get JD\n"));
  782. return USBD_GetDeviceInformationX(
  783. DeviceInformation,
  784. DeviceInformationLength,
  785. DeviceData);
  786. }
  787. PWCHAR
  788. GetString(PWCHAR pwc, BOOLEAN MultiSZ)
  789. {
  790. PWCHAR psz, p;
  791. ULONG Size;
  792. PAGED_CODE();
  793. psz=pwc;
  794. while (*psz!='\0' || (MultiSZ && *(psz+1)!='\0')) {
  795. psz++;
  796. }
  797. Size=(ULONG)(psz-pwc+1+(MultiSZ ? 1: 0))*sizeof(*pwc);
  798. // We use pool here because these pointers are passed
  799. // to the PnP code who is responsible for freeing them
  800. if ((p=ExAllocatePoolWithTag(PagedPool, Size, USBD_TAG))!=NULL) {
  801. RtlCopyMemory(p, pwc, Size);
  802. }
  803. return(p);
  804. }
  805. NTSTATUS
  806. USBD_GetDeviceName(
  807. IN PDEVICE_OBJECT DeviceObject,
  808. IN OUT PUNICODE_STRING DeviceNameUnicodeString
  809. )
  810. /*++
  811. Routine Description:
  812. Returns the device name for the give instance of the HCD
  813. Arguments:
  814. DeviceObject -
  815. DeviceNameUnicodeString - ptr to unicode string to initialize
  816. with device name.
  817. Return Value:
  818. NT status code
  819. --*/
  820. {
  821. ULONG ulActualSize;
  822. NTSTATUS ntStatus;
  823. PAGED_CODE();
  824. ntStatus=IoGetDeviceProperty(DeviceObject,
  825. DevicePropertyPhysicalDeviceObjectName,
  826. 0,
  827. NULL,
  828. &ulActualSize);
  829. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  830. DeviceNameUnicodeString->Length=
  831. (USHORT)(ulActualSize-sizeof(UNICODE_NULL));
  832. DeviceNameUnicodeString->MaximumLength=
  833. (USHORT)ulActualSize;
  834. DeviceNameUnicodeString->Buffer=
  835. ExAllocatePoolWithTag(PagedPool, ulActualSize, USBD_TAG);
  836. if (!DeviceNameUnicodeString->Buffer) {
  837. ntStatus=STATUS_INSUFFICIENT_RESOURCES;
  838. } else {
  839. ntStatus =
  840. IoGetDeviceProperty(DeviceObject,
  841. DevicePropertyPhysicalDeviceObjectName,
  842. ulActualSize,
  843. DeviceNameUnicodeString->Buffer,
  844. &ulActualSize);
  845. if (!NT_SUCCESS(ntStatus)) {
  846. ExFreePool(DeviceNameUnicodeString->Buffer);
  847. }
  848. }
  849. } else {
  850. ntStatus=STATUS_INSUFFICIENT_RESOURCES;
  851. }
  852. return(ntStatus);
  853. }
  854. //
  855. // These functions go away when the PnP naming stuff is fixed
  856. //
  857. UCHAR Instance = 0;
  858. ULONG
  859. USBD_AllocateDeviceName(
  860. PUNICODE_STRING DeviceNameUnicodeString
  861. )
  862. /*++
  863. Routine Description:
  864. Arguments:
  865. Return Value:
  866. None
  867. --*/
  868. {
  869. ULONG bit, i = 0;
  870. PWCHAR deviceNameBuffer;
  871. WCHAR nameBuffer[] = L"\\Device\\HCD0";
  872. //
  873. // first find a free instance value
  874. //
  875. PAGED_CODE();
  876. deviceNameBuffer =
  877. ExAllocatePoolWithTag(NonPagedPool, sizeof(nameBuffer), USBD_TAG);
  878. if (deviceNameBuffer) {
  879. RtlCopyMemory(deviceNameBuffer, nameBuffer, sizeof(nameBuffer));
  880. //
  881. // grab the first free instance
  882. //
  883. bit = 1;
  884. for (i=0; i<8; i++) {
  885. if ((Instance & bit) == 0) {
  886. Instance |= bit;
  887. break;
  888. }
  889. bit = bit <<1;
  890. }
  891. deviceNameBuffer[11] = (WCHAR)('0'+ i);
  892. }
  893. RtlInitUnicodeString(DeviceNameUnicodeString,
  894. deviceNameBuffer);
  895. return i;
  896. }
  897. VOID
  898. USBD_FreeDeviceName(
  899. ULONG DeviceNameHandle
  900. )
  901. /*++
  902. Routine Description:
  903. Arguments:
  904. Return Value:
  905. None
  906. --*/
  907. {
  908. ULONG bit;
  909. PAGED_CODE();
  910. bit = 1;
  911. bit <<= DeviceNameHandle;
  912. Instance &= ~bit;
  913. }
  914. NTSTATUS
  915. USBD_RegisterHostController(
  916. IN PDEVICE_OBJECT PhysicalDeviceObject,
  917. IN PDEVICE_OBJECT HcdDeviceObject,
  918. IN PDEVICE_OBJECT HcdTopOfPdoStackDeviceObject,
  919. IN PDRIVER_OBJECT HcdDriverObject,
  920. IN HCD_DEFFERED_START_FUNCTION *HcdDeferredStartDevice,
  921. IN HCD_SET_DEVICE_POWER_STATE *HcdSetDevicePowerState,
  922. IN HCD_GET_CURRENT_FRAME *HcdGetCurrentFrame,
  923. IN HCD_GET_CONSUMED_BW *HcdGetConsumedBW,
  924. IN HCD_SUBMIT_ISO_URB *HcdSubmitIsoUrb,
  925. // this parameter is only needed until we resolve device naming
  926. // issues with PNP
  927. IN ULONG HcdDeviceNameHandle
  928. )
  929. /*++
  930. Routine Description:
  931. Function is called by HCDs to register with the class driver
  932. Arguments:
  933. PhysicalDeviceObject -
  934. Physical device object representing this bus, this is
  935. the PDO created by PCI and pssed to the HCDs AddDevice
  936. handler.
  937. HcdDeviceObject -
  938. Functional device object (FDO) created by the HCD to manage
  939. the bus
  940. HcdTopOfPdoStackDeviceObject -
  941. device object of for the top of the HCD stack, value returne
  942. from IoAttachDeviceToDeviceStack
  943. Return Value:
  944. --*/
  945. {
  946. NTSTATUS ntStatus = STATUS_SUCCESS;
  947. PDEVICE_OBJECT deviceObject = NULL;
  948. PUSBD_EXTENSION deviceExtension;
  949. UNICODE_STRING localDeviceNameUnicodeString;
  950. PUNICODE_STRING deviceNameUnicodeString;
  951. ULONG complienceFlags = 0;
  952. ULONG diagnosticFlags = 0;
  953. ULONG i;
  954. PAGED_CODE();
  955. USBD_KdPrint(3, ("'enter USBD_RegisterHostController\n"));
  956. ASSERT((sizeof(USBD_EXTENSION) % 4) == 0);
  957. // initialize our device extension, we share the device object
  958. // with the HCD.
  959. deviceExtension = HcdDeviceObject->DeviceExtension;
  960. //#ifdef NTKERN
  961. //
  962. // currently on NTKERN supports the ioclt to get the device name
  963. //
  964. //
  965. // get the device name from the PDO
  966. //
  967. #ifdef USE_PNP_NAME
  968. ntStatus = USBD_GetDeviceName(PnPBusDeviceObject,
  969. &localDeviceNameUnicodeString);
  970. deviceNameUnicodeString = &localDeviceNameUnicodeString;
  971. #else
  972. //
  973. // Big workaround for broken naming of device objects in NTKERN
  974. //
  975. // we would like to use the device name for the PDO but this does not
  976. // work with NTKERN.
  977. //
  978. //
  979. // build device name from handle passed in
  980. //
  981. {
  982. WCHAR nameBuffer[] = L"\\Device\\HCD0";
  983. PWCHAR deviceNameBuffer;
  984. nameBuffer[11] = (WCHAR) ('0'+HcdDeviceNameHandle);
  985. deviceNameBuffer = ExAllocatePoolWithTag(
  986. NonPagedPool,
  987. sizeof(nameBuffer),
  988. USBD_TAG);
  989. if (deviceNameBuffer) {
  990. RtlCopyMemory(deviceNameBuffer, nameBuffer, sizeof(nameBuffer));
  991. } else {
  992. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  993. }
  994. RtlInitUnicodeString(&localDeviceNameUnicodeString,
  995. deviceNameBuffer);
  996. }
  997. #pragma message ("warning: using workaround for bugs in ntkern")
  998. #endif //USE_PNP_NAME
  999. deviceNameUnicodeString = &localDeviceNameUnicodeString;
  1000. if (NT_SUCCESS(ntStatus) && deviceNameUnicodeString) {
  1001. //
  1002. // got the device name, now create a symbolic
  1003. // link for the host HCD/Roothub stack
  1004. //
  1005. //
  1006. // use hardcoded value of HCDn for now until
  1007. // we have a we to get these names from user mode
  1008. //
  1009. WCHAR deviceLinkBuffer[] = L"\\DosDevices\\HCD0";
  1010. WCHAR *buffer;
  1011. deviceLinkBuffer[15] = (WCHAR)('0'+ HcdDeviceNameHandle);
  1012. buffer =
  1013. ExAllocatePoolWithTag(PagedPool, sizeof(deviceLinkBuffer), USBD_TAG);
  1014. if (buffer) {
  1015. RtlCopyMemory(buffer,
  1016. deviceLinkBuffer,
  1017. sizeof(deviceLinkBuffer));
  1018. RtlInitUnicodeString(&deviceExtension->DeviceLinkUnicodeString,
  1019. buffer);
  1020. ntStatus =
  1021. IoCreateSymbolicLink(
  1022. &deviceExtension->DeviceLinkUnicodeString,
  1023. deviceNameUnicodeString);
  1024. USBD_KdPrint(3, ("'IoCreateSymbolicLink for HCD returned 0x%x\n",
  1025. ntStatus));
  1026. // write the symbolic name to the registry
  1027. {
  1028. WCHAR hcdNameKey[] = L"SymbolicName";
  1029. USBD_SetPdoRegistryParameter (
  1030. PhysicalDeviceObject,
  1031. &hcdNameKey[0],
  1032. sizeof(hcdNameKey),
  1033. &deviceExtension->DeviceLinkUnicodeString.Buffer[0],
  1034. deviceExtension->DeviceLinkUnicodeString.Length,
  1035. REG_SZ,
  1036. PLUGPLAY_REGKEY_DEVICE);
  1037. }
  1038. } else {
  1039. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1040. }
  1041. RtlFreeUnicodeString(deviceNameUnicodeString);
  1042. }
  1043. //#endif
  1044. InitializeUsbDeviceMutex(deviceExtension);
  1045. deviceExtension->Length = sizeof(USBD_EXTENSION);
  1046. // Always start with the default address (0) assigned.
  1047. // Address array has one bit for every address 0..127
  1048. deviceExtension->AddressList[0] = 1;
  1049. deviceExtension->AddressList[1] =
  1050. deviceExtension->AddressList[2] =
  1051. deviceExtension->AddressList[3] = 0;
  1052. deviceExtension->FrameLengthControlOwner = NULL;
  1053. deviceExtension->RootHubPDO = NULL;
  1054. deviceExtension->DriverObject = HcdDriverObject;
  1055. deviceExtension->TrueDeviceExtension = deviceExtension;
  1056. deviceExtension->RootHubDeviceState = PowerDeviceD0;
  1057. // initial HC device state is OFF until we get a start
  1058. deviceExtension->HcCurrentDevicePowerState = PowerDeviceD3;
  1059. KeInitializeSpinLock(&deviceExtension->WaitWakeSpin);
  1060. KeInitializeSpinLock(&deviceExtension->RootHubPowerSpin);
  1061. deviceExtension->RootHubPowerDeviceObject = NULL;
  1062. deviceExtension->RootHubPowerIrp = NULL;
  1063. deviceExtension->IdleNotificationIrp = NULL;
  1064. deviceExtension->IsPIIX3or4 = FALSE;
  1065. deviceExtension->WakeSupported = FALSE;
  1066. for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
  1067. deviceExtension->
  1068. RootHubDeviceCapabilities.DeviceState[i] = PowerDeviceD3;
  1069. }
  1070. //#ifndef WAIT_WAKE
  1071. // #pragma message ("warning: using workaround for bugs in ntkern")
  1072. // deviceExtension->HcWakeFlags |= HC_ENABLED_FOR_WAKEUP;
  1073. //#endif
  1074. //
  1075. // intially we are the top of the stack
  1076. //
  1077. deviceExtension->HcdTopOfStackDeviceObject =
  1078. deviceExtension->HcdDeviceObject =
  1079. HcdDeviceObject;
  1080. deviceExtension->HcdPhysicalDeviceObject = PhysicalDeviceObject;
  1081. // remember the top of the PdoStack
  1082. deviceExtension->HcdTopOfPdoStackDeviceObject =
  1083. HcdTopOfPdoStackDeviceObject;
  1084. deviceExtension->HcdDeferredStartDevice =
  1085. HcdDeferredStartDevice;
  1086. deviceExtension->HcdSetDevicePowerState =
  1087. HcdSetDevicePowerState;
  1088. deviceExtension->HcdGetCurrentFrame =
  1089. HcdGetCurrentFrame;
  1090. deviceExtension->HcdGetConsumedBW =
  1091. HcdGetConsumedBW;
  1092. deviceExtension->HcdSubmitIsoUrb =
  1093. HcdSubmitIsoUrb;
  1094. // read params from registry for diagnostic mode and
  1095. // support for non-compliant devices
  1096. USBD_GetPdoRegistryParameters(PhysicalDeviceObject,
  1097. &complienceFlags,
  1098. &diagnosticFlags,
  1099. &deviceExtension->DeviceHackFlags);
  1100. USBD_GetGlobalRegistryParameters(PhysicalDeviceObject,
  1101. &complienceFlags,
  1102. &diagnosticFlags,
  1103. &deviceExtension->DeviceHackFlags);
  1104. deviceExtension->DiagnosticMode = (BOOLEAN) diagnosticFlags;
  1105. deviceExtension->DiagIgnoreHubs = FALSE;
  1106. if (complienceFlags) {
  1107. // support non-com means turn on all hacks
  1108. deviceExtension->DeviceHackFlags = -1;
  1109. }
  1110. #if DBG
  1111. if (deviceExtension->DeviceHackFlags) {
  1112. USBD_KdPrint(1, ("Using DeviceHackFlags (%x)\n",
  1113. deviceExtension->DeviceHackFlags));
  1114. }
  1115. //
  1116. // trap if we detect any special flags set
  1117. //
  1118. if (deviceExtension->DiagnosticMode ||
  1119. complienceFlags) {
  1120. if (deviceExtension->DiagnosticMode) {
  1121. USBD_Warning(NULL,
  1122. "The USB stack is in diagnostic mode\n",
  1123. FALSE);
  1124. if (deviceExtension->DiagIgnoreHubs) {
  1125. USBD_Warning(NULL,
  1126. "The USB stack ignoring HUBs in diag mode\n",
  1127. FALSE);
  1128. }
  1129. }
  1130. if (complienceFlags) {
  1131. USBD_Warning(NULL,
  1132. "Support for non-compliant devices is enabled\n",
  1133. FALSE);
  1134. }
  1135. }
  1136. #endif
  1137. USBD_KdPrint(3, ("'exit USBD_RegisterHostController ext = 0x%x (0x%x)\n",
  1138. deviceExtension, ntStatus));
  1139. return ntStatus;
  1140. }
  1141. NTSTATUS
  1142. USBD_CreateDeviceX(
  1143. IN OUT PUSBD_DEVICE_DATA *DeviceData,
  1144. IN PDEVICE_OBJECT DeviceObject,
  1145. IN BOOLEAN DeviceIsLowSpeed,
  1146. IN ULONG MaxPacketSize_Endpoint0,
  1147. IN OUT PULONG DeviceHackFlags
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. Service exported for use by the hub driver
  1152. Called for each new device on the USB bus, this function sets
  1153. up the internal data structures we need to keep track of the
  1154. device and assigns it an address.
  1155. Arguments:
  1156. DeviceData - ptr to return the ptr to the new device structure
  1157. created by this routine
  1158. DeviceObject - USBD device object for the USB bus this device is on.
  1159. DeviceIsLowSpeed - indicates if a device is low speed
  1160. MaxPacketSize_Endpoint0 (*OPTIONAL*) indicates the default max packet
  1161. size to use when opening endpiint 0.
  1162. NonCompliantDevice (*OPTIONAL*) pointer to boolean flag, set to true
  1163. if support for non-compliant usb devices is enabled.
  1164. Return Value:
  1165. NT status code.
  1166. --*/
  1167. {
  1168. NTSTATUS ntStatus;
  1169. PUSBD_DEVICE_DATA deviceData;
  1170. PUSBD_PIPE defaultPipe;
  1171. PUSBD_EXTENSION deviceExtension;
  1172. ULONG bytesReturned = 0;
  1173. PUCHAR data = NULL;
  1174. PAGED_CODE();
  1175. USBD_KdPrint(3, ("'enter USBD_CreateDevice\n"));
  1176. *DeviceData = NULL;
  1177. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  1178. //USBD_WaitForUsbDeviceMutex(deviceExtension);
  1179. //
  1180. // this flag tells the hub driver to do a reset port before calling
  1181. // initialize_device
  1182. //
  1183. if (DeviceHackFlags) {
  1184. *DeviceHackFlags = deviceExtension->DeviceHackFlags;
  1185. }
  1186. //
  1187. // Allocate a USBD_DEVICE_DATA structure
  1188. //
  1189. deviceData = *DeviceData = GETHEAP(NonPagedPool,
  1190. sizeof(USBD_DEVICE_DATA));
  1191. // buffer for our descriptor
  1192. data = GETHEAP(NonPagedPool,
  1193. USB_DEFAULT_MAX_PACKET);
  1194. if (deviceData != NULL && data != NULL) {
  1195. //
  1196. // Initialize some fields in the device structure
  1197. //
  1198. deviceData->ConfigurationHandle = NULL;
  1199. deviceData->DeviceAddress = USB_DEFAULT_DEVICE_ADDRESS;
  1200. deviceData->LowSpeed = DeviceIsLowSpeed;
  1201. deviceData->AcceptingRequests = TRUE;
  1202. deviceData->Sig = SIG_DEVICE;
  1203. // **
  1204. // We need to talk to the device, first we open the default pipe
  1205. // using the defined max packet size (defined by USB spec as 8
  1206. // bytes until device receives the GET_DESCRIPTOR (device) command).
  1207. // We set the address get the device descriptor then close the pipe
  1208. // and re-open it with the correct max packet size.
  1209. // **
  1210. //
  1211. // open the default pipe for the device
  1212. //
  1213. defaultPipe = &deviceData->DefaultPipe;
  1214. defaultPipe->HcdEndpoint = NULL; //default pipe is closed
  1215. //
  1216. // setup the endpoint descriptor for the default pipe
  1217. //
  1218. defaultPipe->UsbdPipeFlags = 0;
  1219. defaultPipe->EndpointDescriptor.bLength =
  1220. sizeof(USB_ENDPOINT_DESCRIPTOR);
  1221. defaultPipe->EndpointDescriptor.bDescriptorType =
  1222. USB_ENDPOINT_DESCRIPTOR_TYPE;
  1223. defaultPipe->EndpointDescriptor.bEndpointAddress =
  1224. USB_DEFAULT_ENDPOINT_ADDRESS;
  1225. defaultPipe->EndpointDescriptor.bmAttributes =
  1226. USB_ENDPOINT_TYPE_CONTROL;
  1227. defaultPipe->EndpointDescriptor.wMaxPacketSize =
  1228. USB_DEFAULT_MAX_PACKET;
  1229. defaultPipe->EndpointDescriptor.bInterval = 0;
  1230. //
  1231. // probably won't be moving more that 4k on the default pipe
  1232. //
  1233. defaultPipe->MaxTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
  1234. ntStatus = USBD_OpenEndpoint(deviceData,
  1235. DeviceObject,
  1236. defaultPipe,
  1237. NULL,
  1238. TRUE);
  1239. if (NT_SUCCESS(ntStatus)) {
  1240. //
  1241. // Configure the default pipe for this device and assign the
  1242. // device an address
  1243. //
  1244. // NOTE: if this operation fails it means that we have a device
  1245. // that will respond to the default endpoint and we can't change
  1246. // it.
  1247. // we have no choice but to disable the port on the hub this
  1248. // device is attached to.
  1249. //
  1250. //
  1251. // Get information about the device
  1252. //
  1253. ntStatus =
  1254. USBD_SendCommand(deviceData,
  1255. DeviceObject,
  1256. STANDARD_COMMAND_GET_DESCRIPTOR,
  1257. USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(
  1258. USB_DEVICE_DESCRIPTOR_TYPE, 0),
  1259. 0,
  1260. USB_DEFAULT_MAX_PACKET,
  1261. data,
  1262. //(PUCHAR) &deviceData->DeviceDescriptor,
  1263. USB_DEFAULT_MAX_PACKET,
  1264. &bytesReturned,
  1265. NULL);
  1266. // NOTE:
  1267. // at this point we only have the first 8 bytes of the
  1268. // device descriptor.
  1269. }
  1270. //
  1271. // if we got at least the first 8 bytes of the
  1272. // descriptor then we are OK
  1273. //
  1274. RtlCopyMemory(&deviceData->DeviceDescriptor,
  1275. data,
  1276. sizeof(deviceData->DeviceDescriptor));
  1277. if (bytesReturned == 8 && !NT_SUCCESS(ntStatus)) {
  1278. USBD_KdPrint(3,
  1279. ("'Error returned from get device descriptor -- ignored\n"));
  1280. ntStatus = STATUS_SUCCESS;
  1281. }
  1282. // validate the max packet value and descriptor
  1283. if (NT_SUCCESS(ntStatus) &&
  1284. (bytesReturned < 8 ||
  1285. deviceData->DeviceDescriptor.bMaxPacketSize0 == 0)) {
  1286. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1287. }
  1288. if (!NT_SUCCESS(ntStatus)) {
  1289. //
  1290. // something went wrong, if we assigned any resources to
  1291. // the default pipe then we free them before we get out.
  1292. //
  1293. // we need to signal to the parent hub that this
  1294. // port is to be be disabled we will do this by
  1295. // returning an error.
  1296. if (defaultPipe->HcdEndpoint != NULL) {
  1297. USBD_CloseEndpoint(deviceData,
  1298. DeviceObject,
  1299. defaultPipe,
  1300. NULL);
  1301. defaultPipe->HcdEndpoint = NULL; //default pipe is closed
  1302. }
  1303. RETHEAP(deviceData);
  1304. //
  1305. // return a null ptr on error
  1306. //
  1307. *DeviceData = NULL;
  1308. }
  1309. } else {
  1310. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1311. if (deviceData != NULL) {
  1312. RETHEAP(deviceData);
  1313. }
  1314. *DeviceData = NULL;
  1315. }
  1316. if (data != NULL) {
  1317. RETHEAP(data);
  1318. }
  1319. //USBD_ReleaseUsbDeviceMutex(deviceExtension);
  1320. USBD_KdPrint(3, ("'exit USBD_CreateDevice 0x%x\n", ntStatus));
  1321. return ntStatus;
  1322. }
  1323. NTSTATUS
  1324. USBD_CreateDevice(
  1325. IN OUT PUSBD_DEVICE_DATA *DeviceData,
  1326. IN PDEVICE_OBJECT DeviceObject,
  1327. IN BOOLEAN DeviceIsLowSpeed,
  1328. IN ULONG MaxPacketSize_Endpoint0,
  1329. IN OUT PULONG DeviceHackFlags
  1330. )
  1331. {
  1332. USBD_KdPrint(0,
  1333. ("'WARNING: Driver using obsolete service enrty point (USBD_CreateDevice) - get JD\n"));
  1334. return USBD_CreateDeviceX(
  1335. DeviceData,
  1336. DeviceObject,
  1337. DeviceIsLowSpeed,
  1338. MaxPacketSize_Endpoint0,
  1339. DeviceHackFlags
  1340. );
  1341. }
  1342. NTSTATUS
  1343. USBD_RemoveDeviceX(
  1344. IN PUSBD_DEVICE_DATA DeviceData,
  1345. IN PDEVICE_OBJECT DeviceObject,
  1346. IN UCHAR Flags
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. Service exported for use by the hub driver
  1351. Called for each device on the USB bus that needs to be removed.
  1352. This routine frees the device handle and the address assigned
  1353. to the device.
  1354. This function should be called after the driver has been notified
  1355. that the device has been removed.
  1356. Arguments:
  1357. DeviceData - ptr to device data structure created by class driver
  1358. in USBD_CreateDevice.
  1359. DeviceObject - USBD device object for the USB bus this device is on.
  1360. Return Value:
  1361. NT status code.
  1362. --*/
  1363. {
  1364. NTSTATUS ntStatus = STATUS_SUCCESS;
  1365. PUSBD_EXTENSION deviceExtension;
  1366. PUSBD_PIPE defaultPipe;
  1367. USBD_STATUS usbdStatus;
  1368. BOOLEAN keepDeviceData;
  1369. PAGED_CODE();
  1370. USBD_KdPrint(3, ("'enter USBD_RemoveDevice\n"));
  1371. if (!DeviceData || !DeviceObject) {
  1372. USBD_KdPrint(1, ("'NULL parameter passed to USBD_RemoveDevice\n"));
  1373. return STATUS_INVALID_PARAMETER;
  1374. }
  1375. if (DeviceData->Sig != SIG_DEVICE) {
  1376. USBD_KdPrint(1, ("'Bad DeviceData parameter passed to USBD_RemoveDevice\n"));
  1377. return STATUS_INVALID_PARAMETER;
  1378. }
  1379. if (Flags & USBD_MARK_DEVICE_BUSY) {
  1380. DeviceData->AcceptingRequests = FALSE;
  1381. return STATUS_SUCCESS;
  1382. }
  1383. keepDeviceData = Flags & USBD_KEEP_DEVICE_DATA;
  1384. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  1385. USBD_WaitForUsbDeviceMutex(deviceExtension);
  1386. //
  1387. // make sure and clean up any open pipe handles
  1388. // the device may have
  1389. //
  1390. ASSERT_DEVICE(DeviceData);
  1391. DeviceData->AcceptingRequests = FALSE;
  1392. if (DeviceData->ConfigurationHandle) {
  1393. ntStatus = USBD_InternalCloseConfiguration(DeviceData,
  1394. DeviceObject,
  1395. &usbdStatus,
  1396. TRUE,
  1397. keepDeviceData);
  1398. #if DBG
  1399. if (!NT_SUCCESS(ntStatus) ||
  1400. !USBD_SUCCESS(usbdStatus)) {
  1401. USBD_KdTrap(
  1402. ("'error %x usberr %x occurred during RemoveDevice\n",
  1403. ntStatus, usbdStatus));
  1404. }
  1405. #endif
  1406. }
  1407. defaultPipe = &DeviceData->DefaultPipe;
  1408. if (defaultPipe->HcdEndpoint != NULL) {
  1409. USBD_STATUS usbdStatus;
  1410. USBD_InternalCloseDefaultPipe(DeviceData,
  1411. DeviceObject,
  1412. &usbdStatus,
  1413. TRUE);
  1414. // USBD_CloseEndpoint(DeviceData,
  1415. // DeviceObject,
  1416. // defaultPipe,
  1417. // NULL);
  1418. //
  1419. // defaultPipe->HcdEndpoint = NULL; //default pipe is closed
  1420. }
  1421. if (DeviceData->DeviceAddress != USB_DEFAULT_DEVICE_ADDRESS) {
  1422. USBD_FreeUsbAddress(DeviceObject, DeviceData->DeviceAddress);
  1423. }
  1424. if (!keepDeviceData) {
  1425. // zap the signature
  1426. DeviceData->Sig = 0;
  1427. RETHEAP(DeviceData);
  1428. }
  1429. USBD_ReleaseUsbDeviceMutex(deviceExtension);
  1430. USBD_KdPrint(3, ("'exit USBD_RemoveDevice\n"));
  1431. return ntStatus;
  1432. }
  1433. NTSTATUS
  1434. USBD_RemoveDevice(
  1435. IN PUSBD_DEVICE_DATA DeviceData,
  1436. IN PDEVICE_OBJECT DeviceObject,
  1437. IN UCHAR Flags
  1438. )
  1439. {
  1440. USBD_KdPrint(0,
  1441. ("'WARNING: Driver using obsolete service enrty point (USBD_RemoveDevice) - get JD\n"));
  1442. return USBD_RemoveDeviceX(
  1443. DeviceData,
  1444. DeviceObject,
  1445. Flags);
  1446. }
  1447. NTSTATUS
  1448. USBD_InitializeDeviceX(
  1449. IN PUSBD_DEVICE_DATA DeviceData,
  1450. IN PDEVICE_OBJECT DeviceObject,
  1451. IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
  1452. IN ULONG DeviceDescriptorLength,
  1453. IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
  1454. IN ULONG ConfigDescriptorLength
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. Service exported for use by the hub driver
  1459. Called for each device on the USB bus that needs to be initialized.
  1460. This routine allocates an address and assigns it to the device.
  1461. NOTE: on entry the the device descriptor in DeviceData is expected to
  1462. contain at least the first 8 bytes of the device descriptor, this
  1463. information is used to open the default pipe.
  1464. On Error the DeviceData structure is freed.
  1465. Arguments:
  1466. DeviceData - ptr to device data structure created by class driver
  1467. from a call to USBD_CreateDevice.
  1468. DeviceObject - USBD device object for the USB bus this device is on.
  1469. DeviceDescriptor -
  1470. DeviceDescriptorLength -
  1471. Return Value:
  1472. NT status code.
  1473. --*/
  1474. {
  1475. NTSTATUS ntStatus = STATUS_SUCCESS;
  1476. PUSBD_PIPE defaultPipe;
  1477. USHORT address;
  1478. PUSBD_EXTENSION deviceExtension;
  1479. PAGED_CODE();
  1480. USBD_KdPrint(3, ("'enter USBD_InitializeDevice\n"));
  1481. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  1482. //USBD_WaitForUsbDeviceMutex(deviceExtension);
  1483. USBD_ASSERT(DeviceData != NULL);
  1484. defaultPipe = &DeviceData->DefaultPipe;
  1485. //
  1486. // Assign Address to the device
  1487. //
  1488. address = USBD_AllocateUsbAddress(DeviceObject);
  1489. USBD_KdPrint(3, ("'SetAddress, assigning 0x%x address\n", address));
  1490. if (NT_SUCCESS(ntStatus)) {
  1491. ntStatus = USBD_SendCommand(DeviceData,
  1492. DeviceObject,
  1493. STANDARD_COMMAND_SET_ADDRESS,
  1494. address,
  1495. 0,
  1496. 0,
  1497. NULL,
  1498. 0,
  1499. NULL,
  1500. NULL);
  1501. DeviceData->DeviceAddress = address;
  1502. }
  1503. //
  1504. // done with addressing process...
  1505. //
  1506. // close and re-open the pipe utilizing the
  1507. // true max packet size for the defalt pipe
  1508. // and the address we assigned to the device.
  1509. //
  1510. USBD_CloseEndpoint(DeviceData,
  1511. DeviceObject,
  1512. defaultPipe,
  1513. NULL);
  1514. defaultPipe->HcdEndpoint = NULL; //default pipe is closed
  1515. if (NT_SUCCESS(ntStatus)) {
  1516. {
  1517. LARGE_INTEGER deltaTime;
  1518. // 10ms delay to allow devices to respond after
  1519. // the setaddress command
  1520. deltaTime.QuadPart = -100000;
  1521. (VOID) KeDelayExecutionThread(KernelMode,
  1522. FALSE,
  1523. &deltaTime);
  1524. }
  1525. // if we succesfully set the address then
  1526. // go ahead and re-open the pipe.
  1527. defaultPipe->EndpointDescriptor.wMaxPacketSize =
  1528. DeviceData->DeviceDescriptor.bMaxPacketSize0;
  1529. if (NT_SUCCESS(ntStatus)) {
  1530. ntStatus = USBD_OpenEndpoint(DeviceData,
  1531. DeviceObject,
  1532. defaultPipe,
  1533. NULL,
  1534. TRUE);
  1535. }
  1536. //
  1537. // Fetch the device descriptor again, this time
  1538. // get the whole thing.
  1539. //
  1540. if (NT_SUCCESS(ntStatus)) {
  1541. ULONG bytesReturned;
  1542. ntStatus =
  1543. USBD_SendCommand(DeviceData,
  1544. DeviceObject,
  1545. STANDARD_COMMAND_GET_DESCRIPTOR,
  1546. USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(
  1547. USB_DEVICE_DESCRIPTOR_TYPE, 0),
  1548. 0,
  1549. sizeof(DeviceData->DeviceDescriptor),
  1550. (PUCHAR) &DeviceData->DeviceDescriptor,
  1551. sizeof(DeviceData->DeviceDescriptor),
  1552. &bytesReturned,
  1553. NULL);
  1554. if (NT_SUCCESS(ntStatus) &&
  1555. bytesReturned < sizeof(DeviceData->DeviceDescriptor)) {
  1556. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1557. }
  1558. }
  1559. //
  1560. // Fetch the configuration descriptor for the user as well
  1561. // so we can see how many interfaces there are in the configuration.
  1562. // If this is a multiple interface device we might want to load
  1563. // the standard mulitple interface parent driver instead of the
  1564. // diagnostic driver.
  1565. //
  1566. // The 9 byte configuration descriptor is cached in the DeviceData
  1567. // used by USBD_BusGetUsbDescriptors() later instead of bothering
  1568. // the device with another Get Descriptor request again real soon.
  1569. // Some devices don't take too well to being bothered with back to
  1570. // back Get Descriptor requests for only the 9 byte header, especially
  1571. // on OHCI host controllers.
  1572. if (NT_SUCCESS(ntStatus)) {
  1573. ULONG bytesReturned;
  1574. ntStatus =
  1575. USBD_SendCommand(DeviceData,
  1576. DeviceObject,
  1577. STANDARD_COMMAND_GET_DESCRIPTOR,
  1578. USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(
  1579. USB_CONFIGURATION_DESCRIPTOR_TYPE, 0),
  1580. 0,
  1581. sizeof(DeviceData->ConfigDescriptor),
  1582. (PUCHAR) &DeviceData->ConfigDescriptor,
  1583. sizeof(DeviceData->ConfigDescriptor),
  1584. &bytesReturned,
  1585. NULL);
  1586. if (NT_SUCCESS(ntStatus) &&
  1587. bytesReturned < sizeof(DeviceData->ConfigDescriptor)) {
  1588. ntStatus = STATUS_DEVICE_DATA_ERROR;
  1589. }
  1590. }
  1591. }
  1592. if (NT_SUCCESS(ntStatus)) {
  1593. //
  1594. // Return copies of the device and the config descriptors to the caller
  1595. //
  1596. if (deviceExtension->DiagnosticMode &&
  1597. !(deviceExtension->DiagIgnoreHubs &&
  1598. (DeviceData->DeviceDescriptor.bDeviceClass == 0x09)))
  1599. {
  1600. if (DeviceData->ConfigDescriptor.bNumInterfaces > 1){
  1601. /*
  1602. * This is a COMPOSITE device.
  1603. * Alter idProduct slightly so that diagnostic driver
  1604. * doesn't load for the parent device.
  1605. * The Generic Parent driver will see this and
  1606. * set the vid/pid for children to FFFF/FFFF
  1607. */
  1608. DeviceData->DeviceDescriptor.idVendor = 0xFFFF;
  1609. DeviceData->DeviceDescriptor.idProduct = 0xFFFE;
  1610. }
  1611. else {
  1612. DeviceData->DeviceDescriptor.idVendor = 0xFFFF;
  1613. DeviceData->DeviceDescriptor.idProduct = 0xFFFF;
  1614. }
  1615. DeviceData->DeviceDescriptor.bDeviceClass = 0;
  1616. DeviceData->DeviceDescriptor.bDeviceSubClass = 0;
  1617. }
  1618. if (DeviceDescriptor) {
  1619. RtlCopyMemory(DeviceDescriptor,
  1620. &DeviceData->DeviceDescriptor,
  1621. DeviceDescriptorLength);
  1622. }
  1623. if (ConfigDescriptor) {
  1624. RtlCopyMemory(ConfigDescriptor,
  1625. &DeviceData->ConfigDescriptor,
  1626. ConfigDescriptorLength);
  1627. }
  1628. } else {
  1629. //
  1630. // something went wrong, if we assigned any resources to
  1631. // the default pipe then we free them before we get out.
  1632. //
  1633. // we need to signal to the parent hub that this
  1634. // port is to be be disabled we will do this by
  1635. // returning an error.
  1636. if (defaultPipe->HcdEndpoint != NULL) {
  1637. USBD_CloseEndpoint(DeviceData,
  1638. DeviceObject,
  1639. defaultPipe,
  1640. NULL);
  1641. defaultPipe->HcdEndpoint = NULL; //default pipe is closed
  1642. }
  1643. if (DeviceData->DeviceAddress != USB_DEFAULT_DEVICE_ADDRESS) {
  1644. USBD_FreeUsbAddress(DeviceObject, DeviceData->DeviceAddress);
  1645. }
  1646. RETHEAP(DeviceData);
  1647. }
  1648. //USBD_ReleaseUsbDeviceMutex(deviceExtension);
  1649. USBD_KdPrint(3, ("'exit USBD_InitializeDevice 0x%x\n", ntStatus));
  1650. return ntStatus;
  1651. }
  1652. NTSTATUS
  1653. USBD_InitializeDevice(
  1654. IN PUSBD_DEVICE_DATA DeviceData,
  1655. IN PDEVICE_OBJECT DeviceObject,
  1656. IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
  1657. IN ULONG DeviceDescriptorLength,
  1658. IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
  1659. IN ULONG ConfigDescriptorLength
  1660. )
  1661. {
  1662. USBD_KdPrint(0,
  1663. ("'WARNING: Driver using obsolete service enrty point (USBD_InitializeDevice) - get JD\n"));
  1664. return USBD_InitializeDeviceX(
  1665. DeviceData,
  1666. DeviceObject,
  1667. DeviceDescriptor,
  1668. DeviceDescriptorLength,
  1669. ConfigDescriptor,
  1670. ConfigDescriptorLength);
  1671. }
  1672. BOOLEAN
  1673. USBD_Dispatch(
  1674. PDEVICE_OBJECT DeviceObject,
  1675. PIRP Irp,
  1676. PDEVICE_OBJECT *HcdDeviceObject,
  1677. NTSTATUS *NtStatus
  1678. )
  1679. /*++
  1680. Routine Description:
  1681. Entry point called by HCD to allow USBD to process requests first. Since
  1682. the root hub (PDO) and the Hos cOntroller FDO share the same dispatch
  1683. routine. The HCD calls this function to allow USBD to handle Irps passed
  1684. to the PDO for the root hub.
  1685. Arguments:
  1686. Return Value:
  1687. FALSE = Irp completed by USBD
  1688. TRUE = Irp needs completion by HCD
  1689. --*/
  1690. {
  1691. BOOLEAN irpNeedsCompletion = TRUE;
  1692. PUSBD_EXTENSION deviceExtension;
  1693. BOOLEAN forPDO = FALSE;
  1694. PIO_STACK_LOCATION irpStack;
  1695. USBD_KdPrint(3, ("'enter USBD_Dispatch\n"));
  1696. irpStack = IoGetCurrentIrpStackLocation (Irp);
  1697. deviceExtension = DeviceObject->DeviceExtension;
  1698. //
  1699. // apparently the following is valid on NT:
  1700. // remove rh PDO
  1701. // remove hcd FDO
  1702. // remove rh PDO
  1703. // we have a special flag to force failure of any PnP IRPs
  1704. // in case this happens
  1705. //
  1706. if (deviceExtension->Flags & USBDFLAG_PDO_REMOVED &&
  1707. irpStack->MajorFunction == IRP_MJ_PNP &&
  1708. deviceExtension->TrueDeviceExtension != deviceExtension) {
  1709. irpNeedsCompletion = FALSE;
  1710. USBD_KdPrint(0, ("'Warning: PNP irp for RH PDO received after HCD removed\n"));
  1711. *NtStatus =
  1712. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  1713. USBD_IoCompleteRequest (Irp,
  1714. IO_NO_INCREMENT);
  1715. return irpNeedsCompletion;
  1716. }
  1717. if (deviceExtension->TrueDeviceExtension != deviceExtension) {
  1718. // This request is for a PDO we created for the
  1719. // root hub
  1720. deviceExtension = deviceExtension->TrueDeviceExtension;
  1721. forPDO = TRUE;
  1722. }
  1723. //
  1724. // extract the host controller FDO and return it.
  1725. //
  1726. *HcdDeviceObject = deviceExtension->HcdDeviceObject;
  1727. if (forPDO) {
  1728. irpNeedsCompletion = FALSE;
  1729. *NtStatus = USBD_PdoDispatch(DeviceObject,
  1730. Irp,
  1731. deviceExtension,
  1732. &irpNeedsCompletion);
  1733. } else {
  1734. *NtStatus = USBD_FdoDispatch(DeviceObject,
  1735. Irp,
  1736. deviceExtension,
  1737. &irpNeedsCompletion);
  1738. }
  1739. //
  1740. // this flag tells the HCD if they should handle the Irp.
  1741. //
  1742. return irpNeedsCompletion;
  1743. }
  1744. VOID
  1745. USBD_RhDelayedSetPowerD0Worker(
  1746. IN PVOID Context)
  1747. /* ++
  1748. *
  1749. * Description:
  1750. *
  1751. * Work item scheduled to handle a delayed Set Power D0 IRP for the root hub.
  1752. *
  1753. *
  1754. * Arguments:
  1755. *
  1756. * Return:
  1757. *
  1758. * -- */
  1759. {
  1760. PUSBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM workItemSetPowerD0;
  1761. NTSTATUS ntStatus = STATUS_SUCCESS;
  1762. PUSBD_EXTENSION deviceExtension = NULL;
  1763. PDEVICE_OBJECT rootHubPowerDeviceObject = NULL;
  1764. PIRP rootHubPowerIrp = NULL;
  1765. PIO_STACK_LOCATION irpStack;
  1766. PAGED_CODE();
  1767. workItemSetPowerD0 = Context;
  1768. deviceExtension = workItemSetPowerD0->DeviceExtension;
  1769. rootHubPowerDeviceObject = workItemSetPowerD0->DeviceObject;
  1770. rootHubPowerIrp = workItemSetPowerD0->Irp;
  1771. ExFreePool(Context);
  1772. irpStack = IoGetCurrentIrpStackLocation(rootHubPowerIrp);
  1773. ntStatus = deviceExtension->RootHubPower(
  1774. deviceExtension->HcdDeviceObject,
  1775. rootHubPowerIrp);
  1776. // notify after we go on
  1777. PoSetPowerState(rootHubPowerDeviceObject,
  1778. DevicePowerState,
  1779. irpStack->Parameters.Power.State);
  1780. //
  1781. // keep track of the power state for this PDO
  1782. //
  1783. deviceExtension->RootHubDeviceState =
  1784. irpStack->Parameters.Power.State.DeviceState;
  1785. USBD_CompleteIdleNotification(deviceExtension);
  1786. rootHubPowerIrp->IoStatus.Status = ntStatus;
  1787. PoStartNextPowerIrp(rootHubPowerIrp);
  1788. USBD_IoCompleteRequest(rootHubPowerIrp, IO_NO_INCREMENT);
  1789. }
  1790. VOID
  1791. USBD_CompleteIdleNotification(
  1792. IN PUSBD_EXTENSION DeviceExtension
  1793. )
  1794. {
  1795. NTSTATUS status;
  1796. KIRQL irql;
  1797. PIRP irp = NULL;
  1798. IoAcquireCancelSpinLock(&irql);
  1799. irp = DeviceExtension->IdleNotificationIrp;
  1800. DeviceExtension->IdleNotificationIrp = NULL;
  1801. if (irp && (irp->Cancel)) {
  1802. irp = NULL;
  1803. }
  1804. if (irp) {
  1805. IoSetCancelRoutine(irp, NULL);
  1806. }
  1807. IoReleaseCancelSpinLock(irql);
  1808. if (irp) {
  1809. irp->IoStatus.Status = STATUS_SUCCESS;
  1810. IoCompleteRequest(irp, IO_NO_INCREMENT);
  1811. }
  1812. }
  1813. NTSTATUS
  1814. USBD_HcPoRequestD0Completion(
  1815. IN PDEVICE_OBJECT DeviceObject,
  1816. IN UCHAR MinorFunction,
  1817. IN POWER_STATE PowerState,
  1818. IN PVOID Context,
  1819. IN PIO_STATUS_BLOCK IoStatus
  1820. )
  1821. /*++
  1822. Routine Description:
  1823. Arguments:
  1824. DeviceObject - Pointer to the device object for the class device.
  1825. Irp - Irp completed.
  1826. Context - Driver defined context.
  1827. Return Value:
  1828. The function value is the final status from the operation.
  1829. --*/
  1830. {
  1831. PUSBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM workItemSetPowerD0;
  1832. NTSTATUS ntStatus;
  1833. PUSBD_EXTENSION deviceExtension = Context;
  1834. KIRQL irql;
  1835. PIRP pendingWakeIrp;
  1836. PDEVICE_OBJECT rootHubPowerDeviceObject = NULL;
  1837. PIRP rootHubPowerIrp = NULL;
  1838. ntStatus = IoStatus->Status;
  1839. USBD_KdPrint(1, ("USBD_HcPoRequestD0Completion, status = %x\n", ntStatus));
  1840. KeAcquireSpinLock(&deviceExtension->RootHubPowerSpin,
  1841. &irql);
  1842. deviceExtension->Flags &= ~USBDFLAG_HCD_D0_COMPLETE_PENDING;
  1843. if (deviceExtension->Flags & USBDFLAG_RH_DELAY_SET_D0) {
  1844. deviceExtension->Flags &= ~USBDFLAG_RH_DELAY_SET_D0;
  1845. rootHubPowerDeviceObject = deviceExtension->RootHubPowerDeviceObject;
  1846. deviceExtension->RootHubPowerDeviceObject = NULL;
  1847. rootHubPowerIrp = deviceExtension->RootHubPowerIrp;
  1848. deviceExtension->RootHubPowerIrp = NULL;
  1849. }
  1850. KeReleaseSpinLock(&deviceExtension->RootHubPowerSpin,
  1851. irql);
  1852. // Power up the RootHub now if we delayed it waiting for the HC set D0
  1853. // to complete.
  1854. if (rootHubPowerIrp) {
  1855. //
  1856. // Schedule a work item to process this.
  1857. //
  1858. workItemSetPowerD0 =
  1859. ExAllocatePoolWithTag(NonPagedPool,
  1860. sizeof(USBD_RH_DELAYED_SET_POWER_D0_WORK_ITEM),
  1861. USBD_TAG);
  1862. if (workItemSetPowerD0) {
  1863. workItemSetPowerD0->DeviceExtension = deviceExtension;
  1864. workItemSetPowerD0->DeviceObject = rootHubPowerDeviceObject;
  1865. workItemSetPowerD0->Irp = rootHubPowerIrp;
  1866. ExInitializeWorkItem(&workItemSetPowerD0->WorkQueueItem,
  1867. USBD_RhDelayedSetPowerD0Worker,
  1868. workItemSetPowerD0);
  1869. ExQueueWorkItem(&workItemSetPowerD0->WorkQueueItem,
  1870. DelayedWorkQueue);
  1871. }
  1872. }
  1873. //
  1874. // no wakeup irp pending
  1875. //
  1876. // The only race condition we our concerned about is if
  1877. // the wait wake irp is completed while another is submitted.
  1878. // the WaitWake spinlock protects us in this case
  1879. KeAcquireSpinLock(&deviceExtension->WaitWakeSpin,
  1880. &irql);
  1881. pendingWakeIrp = deviceExtension->PendingWakeIrp;
  1882. deviceExtension->PendingWakeIrp = NULL;
  1883. deviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  1884. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  1885. irql);
  1886. // we just keep the irp pending until it is canceled
  1887. //
  1888. // this means that the HC was the source of
  1889. // a wakeup ie a usbd device generated resume
  1890. // signalling on the bus
  1891. //
  1892. // complete the root hub wakeup irp here
  1893. if (pendingWakeIrp != NULL) {
  1894. IoAcquireCancelSpinLock(&irql);
  1895. if (pendingWakeIrp->Cancel) {
  1896. IoReleaseCancelSpinLock(irql);
  1897. } else {
  1898. IoSetCancelRoutine(pendingWakeIrp, NULL);
  1899. IoReleaseCancelSpinLock(irql);
  1900. // status of this Irp?
  1901. pendingWakeIrp->IoStatus = *IoStatus;
  1902. USBD_IoCompleteRequest(pendingWakeIrp, IO_NO_INCREMENT);
  1903. }
  1904. }
  1905. return ntStatus;
  1906. }
  1907. NTSTATUS
  1908. USBD_HcWaitWakeIrpCompletion(
  1909. IN PDEVICE_OBJECT DeviceObject,
  1910. IN UCHAR MinorFunction,
  1911. IN POWER_STATE DeviceState,
  1912. IN PVOID Context,
  1913. IN PIO_STATUS_BLOCK IoStatus
  1914. )
  1915. /*++
  1916. Routine Description:
  1917. Called when a wake irp completes for a hub
  1918. Arguments:
  1919. DeviceObject - Pointer to the device object for the class device.
  1920. Irp - Irp completed.
  1921. Context - Driver defined context.
  1922. Return Value:
  1923. The function value is the final status from the operation.
  1924. --*/
  1925. {
  1926. NTSTATUS ntStatus = IoStatus->Status;
  1927. PUSBD_EXTENSION deviceExtension = Context;
  1928. PIRP irp;
  1929. KIRQL irql;
  1930. PIRP pendingWakeIrp;
  1931. POWER_STATE powerState;
  1932. BOOLEAN bSubmitNewWakeIrp = FALSE;
  1933. ntStatus = IoStatus->Status;
  1934. USBD_KdPrint(1, ("WaitWake completion from HC %x\n", ntStatus));
  1935. // Clear HcWakeIrp pointer now, otherwise we might try to cancel it in
  1936. // USBD_WaitWakeCancel if it is called before our set D0 completes where
  1937. // we used to clear HcWakeIrp.
  1938. //
  1939. // We are still protected from untimely submittal of a new HcWakeIrp
  1940. // because this cannot happen until the PendingWakeIrp pointer (for
  1941. // the RootHub) is cleared.
  1942. KeAcquireSpinLock(&deviceExtension->WaitWakeSpin,
  1943. &irql);
  1944. // no irp pending in the HC
  1945. deviceExtension->HcWakeFlags &= ~HC_WAKE_PENDING;
  1946. deviceExtension->HcWakeIrp = NULL;
  1947. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  1948. irql);
  1949. if (NT_SUCCESS(ntStatus)) {
  1950. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  1951. powerState.DeviceState = PowerDeviceD0;
  1952. ntStatus = PoRequestPowerIrp(deviceExtension->
  1953. HcdPhysicalDeviceObject,
  1954. IRP_MN_SET_POWER,
  1955. powerState,
  1956. USBD_HcPoRequestD0Completion,
  1957. deviceExtension,
  1958. &irp);
  1959. USBD_KdPrint(1, ("NTSTATUS return code from HC set D0 request %x, IRP: %x\n", ntStatus, irp));
  1960. ASSERT(ntStatus == STATUS_PENDING);
  1961. if (ntStatus == STATUS_PENDING) {
  1962. deviceExtension->Flags |= USBDFLAG_HCD_D0_COMPLETE_PENDING;
  1963. }
  1964. } else {
  1965. // The only race condition we our concerned about is if
  1966. // the wait wake irp is completed wile another is submitted.
  1967. // the WaitWake spinlock protects us in this case
  1968. KeAcquireSpinLock(&deviceExtension->WaitWakeSpin,
  1969. &irql);
  1970. pendingWakeIrp = deviceExtension->PendingWakeIrp;
  1971. deviceExtension->PendingWakeIrp = NULL;
  1972. deviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  1973. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  1974. irql);
  1975. //
  1976. // Complete the root hub wakeup irp here.
  1977. //
  1978. if (pendingWakeIrp != NULL) {
  1979. IoAcquireCancelSpinLock(&irql);
  1980. if (pendingWakeIrp->Cancel) {
  1981. IoReleaseCancelSpinLock(irql);
  1982. } else {
  1983. IoSetCancelRoutine(pendingWakeIrp, NULL);
  1984. IoReleaseCancelSpinLock(irql);
  1985. // status of this Irp?
  1986. pendingWakeIrp->IoStatus = *IoStatus;
  1987. USBD_IoCompleteRequest(pendingWakeIrp, IO_NO_INCREMENT);
  1988. }
  1989. }
  1990. }
  1991. KeAcquireSpinLock(&deviceExtension->WaitWakeSpin,
  1992. &irql);
  1993. bSubmitNewWakeIrp =
  1994. (deviceExtension->Flags & USBDFLAG_NEED_NEW_HCWAKEIRP) ? 1 : 0;
  1995. deviceExtension->Flags &= ~USBDFLAG_NEED_NEW_HCWAKEIRP;
  1996. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  1997. irql);
  1998. if (bSubmitNewWakeIrp) {
  1999. USBD_SubmitWaitWakeIrpToHC(deviceExtension);
  2000. }
  2001. return ntStatus;
  2002. }
  2003. NTSTATUS
  2004. USBD_SubmitWaitWakeIrpToHC(
  2005. IN PUSBD_EXTENSION DeviceExtension
  2006. )
  2007. /*++
  2008. Routine Description:
  2009. called when a child Pdo is enabled for wakeup, this
  2010. function allocates a wait wake irp and passes it to
  2011. the parents PDO.
  2012. Arguments:
  2013. Return Value:
  2014. --*/
  2015. {
  2016. PIRP irp;
  2017. NTSTATUS ntStatus;
  2018. POWER_STATE powerState;
  2019. KIRQL irql;
  2020. PIRP hcWakeIrp;
  2021. KeAcquireSpinLock(&DeviceExtension->WaitWakeSpin,
  2022. &irql);
  2023. hcWakeIrp = DeviceExtension->HcWakeIrp;
  2024. if (hcWakeIrp && hcWakeIrp->Cancel &&
  2025. !(DeviceExtension->Flags & USBDFLAG_NEED_NEW_HCWAKEIRP)) {
  2026. DeviceExtension->Flags |= USBDFLAG_NEED_NEW_HCWAKEIRP;
  2027. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  2028. irql);
  2029. // If we allow a new WW IRP to be posted for the HC now, it will be
  2030. // completed with an error because the previous one has not been
  2031. // completed/canceled yet. So we set a flag that tells the HC WW IRP
  2032. // completion routine that it needs to submit the WW IRP for the HC.
  2033. USBD_KdPrint(1, (" HC will be re-enabled for wakeup when old WW IRP completes.\n"));
  2034. return STATUS_PENDING;
  2035. } else {
  2036. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  2037. irql);
  2038. }
  2039. USBD_ASSERT(DeviceExtension->HcWakeIrp == NULL);
  2040. // call top of HC driver stack
  2041. DeviceExtension->HcWakeFlags |= HC_WAKE_PENDING;
  2042. powerState.DeviceState = DeviceExtension->HcDeviceCapabilities.SystemWake;
  2043. USBD_KdPrint(1, ("Submitting IRP_MN_WAIT_WAKE to HC, powerState: %x\n",
  2044. DeviceExtension->HcDeviceCapabilities.SystemWake));
  2045. ntStatus = PoRequestPowerIrp(DeviceExtension->
  2046. HcdPhysicalDeviceObject,
  2047. IRP_MN_WAIT_WAKE,
  2048. powerState,
  2049. USBD_HcWaitWakeIrpCompletion,
  2050. DeviceExtension,
  2051. &irp);
  2052. if (DeviceExtension->HcWakeFlags & HC_WAKE_PENDING) {
  2053. DeviceExtension->HcWakeIrp = irp;
  2054. USBD_KdPrint(1, (" HC enabled for wakeup\n"));
  2055. }
  2056. USBD_ASSERT(ntStatus == STATUS_PENDING);
  2057. return ntStatus;
  2058. }
  2059. VOID
  2060. USBD_WaitWakeCancel(
  2061. IN PDEVICE_OBJECT DeviceObject,
  2062. IN PIRP Irp
  2063. )
  2064. /*++
  2065. Routine Description:
  2066. Arguments:
  2067. Return Value:
  2068. NT status code.
  2069. --*/
  2070. {
  2071. PUSBD_EXTENSION deviceExtension;
  2072. KIRQL irql;
  2073. USBD_KdPrint(3, ("'WaitWake Irp %x cancelled\n", Irp));
  2074. USBD_ASSERT(Irp->Cancel == TRUE);
  2075. deviceExtension = (PUSBD_EXTENSION)
  2076. Irp->IoStatus.Information;
  2077. USBD_ASSERT(deviceExtension != NULL);
  2078. Irp->IoStatus.Status = STATUS_CANCELLED;
  2079. Irp->IoStatus.Information = 0;
  2080. IoReleaseCancelSpinLock(Irp->CancelIrql);
  2081. KeAcquireSpinLock(&deviceExtension->WaitWakeSpin,
  2082. &irql);
  2083. deviceExtension->PendingWakeIrp = NULL;
  2084. deviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  2085. // see if we need to cancel a wake irp
  2086. // in the HC
  2087. if (deviceExtension->HcWakeIrp) {
  2088. PIRP irp;
  2089. irp = deviceExtension->HcWakeIrp;
  2090. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  2091. irql);
  2092. USBD_KdPrint(1, (" Canceling Wake Irp (%x) on HC PDO\n", irp));
  2093. IoCancelIrp(irp);
  2094. } else {
  2095. KeReleaseSpinLock(&deviceExtension->WaitWakeSpin,
  2096. irql);
  2097. }
  2098. USBD_IoCompleteRequest (Irp,
  2099. IO_NO_INCREMENT);
  2100. }
  2101. NTSTATUS
  2102. USBD_PdoPower(
  2103. PDEVICE_OBJECT DeviceObject,
  2104. PIRP Irp,
  2105. PUSBD_EXTENSION DeviceExtension
  2106. )
  2107. /*++
  2108. Routine Description:
  2109. Disptach routine for Power Irps sent to the PDO for the root hub.
  2110. NOTE:
  2111. irps sent to the PDO are always completed by the bus driver
  2112. Arguments:
  2113. DeviceObject - Pdo for the root hub
  2114. Return Value:
  2115. None
  2116. --*/
  2117. {
  2118. PIO_STACK_LOCATION irpStack;
  2119. NTSTATUS ntStatus;
  2120. KIRQL irql;
  2121. PDRIVER_CANCEL oldCancel;
  2122. PDEVICE_CAPABILITIES hcDeviceCapabilities;
  2123. PIRP irp, waitWakeIrp = NULL, idleIrp = NULL;
  2124. POWER_STATE powerState;
  2125. USBD_KdPrint(3, ("'enter USBD_PdoPower\n"));
  2126. PAGED_CODE();
  2127. irpStack = IoGetCurrentIrpStackLocation (Irp);
  2128. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  2129. switch (irpStack->MinorFunction) {
  2130. case IRP_MN_SET_POWER:
  2131. USBD_KdPrint(3, ("'IRP_MN_SET_POWER root hub PDO\n"));
  2132. switch (irpStack->Parameters.Power.Type) {
  2133. case SystemPowerState:
  2134. {
  2135. //
  2136. // since the fdo driver for the root hub pdo is our own
  2137. // hub driver and it is well behaved, we don't expect to see
  2138. // a system message where the power state is still undefined
  2139. //
  2140. //
  2141. // we just complete this with success
  2142. //
  2143. ntStatus = STATUS_SUCCESS;
  2144. USBD_KdPrint(1,
  2145. ("IRP_MJ_POWER RH pdo(%x) MN_SET_POWER(SystemPowerState S%x) status = %x complt\n",
  2146. DeviceObject,
  2147. irpStack->Parameters.Power.State.SystemState - 1,
  2148. ntStatus));
  2149. if (irpStack->Parameters.Power.State.SystemState >=
  2150. PowerSystemShutdown) {
  2151. USBD_KdPrint(1, ("Shutdown Detected for Root Hub PDO\n",
  2152. DeviceObject, ntStatus));
  2153. }
  2154. }
  2155. break;
  2156. case DevicePowerState:
  2157. USBD_KdPrint(1,
  2158. ("IRP_MJ_POWER RH pdo(%x) MN_SET_POWER(DevicePowerState D%x) from (D%x)\n",
  2159. DeviceObject,
  2160. irpStack->Parameters.Power.State.DeviceState - 1,
  2161. DeviceExtension->RootHubDeviceState - 1));
  2162. if (irpStack->Parameters.Power.State.DeviceState ==
  2163. PowerDeviceD0) {
  2164. KeAcquireSpinLock(&DeviceExtension->RootHubPowerSpin,
  2165. &irql);
  2166. // Don't power up root hub yet if the HC is not at D0.
  2167. if (DeviceExtension->HcCurrentDevicePowerState == PowerDeviceD0 &&
  2168. !(DeviceExtension->Flags & USBDFLAG_HCD_D0_COMPLETE_PENDING)) {
  2169. KeReleaseSpinLock(&DeviceExtension->RootHubPowerSpin,
  2170. irql);
  2171. ntStatus =
  2172. DeviceExtension->RootHubPower(
  2173. DeviceExtension->HcdDeviceObject,
  2174. Irp);
  2175. // notify after we go on
  2176. PoSetPowerState(DeviceObject,
  2177. DevicePowerState,
  2178. irpStack->Parameters.Power.State);
  2179. USBD_CompleteIdleNotification(DeviceExtension);
  2180. } else if (!(DeviceExtension->Flags & USBDFLAG_RH_DELAY_SET_D0)) {
  2181. DeviceExtension->Flags |= USBDFLAG_RH_DELAY_SET_D0;
  2182. ASSERT(DeviceExtension->RootHubPowerDeviceObject == NULL);
  2183. ASSERT(DeviceExtension->RootHubPowerIrp == NULL);
  2184. DeviceExtension->RootHubPowerDeviceObject = DeviceObject;
  2185. DeviceExtension->RootHubPowerIrp = Irp;
  2186. KeReleaseSpinLock(&DeviceExtension->RootHubPowerSpin,
  2187. irql);
  2188. USBD_KdPrint(1, ("'USBD_PdoPower, not powering up RootHub yet because HC is not at D0.\n"));
  2189. KeAcquireSpinLock(&DeviceExtension->WaitWakeSpin,
  2190. &irql);
  2191. // see if we need to cancel a wake irp
  2192. // in the HC
  2193. if (DeviceExtension->HcWakeIrp) {
  2194. PIRP hcwakeirp;
  2195. hcwakeirp = DeviceExtension->HcWakeIrp;
  2196. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  2197. irql);
  2198. USBD_KdPrint(1, ("USBD_PdoPower, Set D0: Canceling Wake Irp (%x) on HC PDO\n", hcwakeirp));
  2199. IoCancelIrp(hcwakeirp);
  2200. } else {
  2201. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  2202. irql);
  2203. }
  2204. // Set the HC to D0 now.
  2205. powerState.DeviceState = PowerDeviceD0;
  2206. ntStatus = PoRequestPowerIrp(DeviceExtension->
  2207. HcdPhysicalDeviceObject,
  2208. IRP_MN_SET_POWER,
  2209. powerState,
  2210. USBD_HcPoRequestD0Completion,
  2211. DeviceExtension,
  2212. &irp);
  2213. USBD_KdPrint(1, ("NTSTATUS return code from HC set D0 request %x, IRP: %x\n", ntStatus, irp));
  2214. ASSERT(ntStatus == STATUS_PENDING);
  2215. goto USBD_PdoPower_Done;
  2216. } else {
  2217. KeReleaseSpinLock(&DeviceExtension->RootHubPowerSpin,
  2218. irql);
  2219. // Root Hub set D0 is already pending, just complete this
  2220. // IRP with STATUS_SUCCESS.
  2221. ntStatus = STATUS_SUCCESS;
  2222. }
  2223. } else {
  2224. //
  2225. // Complete the Wait Wake Irp if we are going to D3.
  2226. //
  2227. // We take the cancel spinlock here to ensure our cancel routine does
  2228. // not complete the Irp for us.
  2229. //
  2230. if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
  2231. IoAcquireCancelSpinLock(&irql);
  2232. if (DeviceExtension->IdleNotificationIrp) {
  2233. idleIrp = DeviceExtension->IdleNotificationIrp;
  2234. DeviceExtension->IdleNotificationIrp = NULL;
  2235. if (idleIrp->Cancel) {
  2236. idleIrp = NULL;
  2237. }
  2238. if (idleIrp) {
  2239. IoSetCancelRoutine(idleIrp, NULL);
  2240. }
  2241. }
  2242. if (DeviceExtension->PendingWakeIrp) {
  2243. waitWakeIrp = DeviceExtension->PendingWakeIrp;
  2244. DeviceExtension->PendingWakeIrp = NULL;
  2245. DeviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  2246. // irp can no longer be cancelled
  2247. if (waitWakeIrp->Cancel || IoSetCancelRoutine(waitWakeIrp, NULL) == NULL) {
  2248. waitWakeIrp = NULL;
  2249. }
  2250. }
  2251. IoReleaseCancelSpinLock(irql);
  2252. if (idleIrp) {
  2253. idleIrp->IoStatus.Status = STATUS_POWER_STATE_INVALID;
  2254. IoCompleteRequest(idleIrp, IO_NO_INCREMENT);
  2255. }
  2256. if (waitWakeIrp) {
  2257. waitWakeIrp->IoStatus.Status = STATUS_POWER_STATE_INVALID;
  2258. PoStartNextPowerIrp(waitWakeIrp);
  2259. USBD_IoCompleteRequest(waitWakeIrp, IO_NO_INCREMENT);
  2260. }
  2261. }
  2262. // notify before we go off
  2263. PoSetPowerState(DeviceObject,
  2264. DevicePowerState,
  2265. irpStack->Parameters.Power.State);
  2266. ntStatus =
  2267. DeviceExtension->RootHubPower(
  2268. DeviceExtension->HcdDeviceObject,
  2269. Irp);
  2270. }
  2271. //
  2272. // keep track of the power state for this PDO
  2273. //
  2274. DeviceExtension->RootHubDeviceState =
  2275. irpStack->Parameters.Power.State.DeviceState;
  2276. USBD_KdPrint(1,
  2277. ("Setting RH pdo(%x) to D%d, status = %x complt\n",
  2278. DeviceObject,
  2279. DeviceExtension->RootHubDeviceState-1,
  2280. ntStatus));
  2281. break;
  2282. default:
  2283. USBD_KdTrap(("unknown system power message \n"));
  2284. ntStatus = Irp->IoStatus.Status;
  2285. }
  2286. break;
  2287. case IRP_MN_QUERY_POWER:
  2288. ntStatus = STATUS_SUCCESS;
  2289. USBD_KdPrint(1,
  2290. ("IRP_MJ_POWER RH pdo(%x) MN_QUERY_POWER, status = %x complt\n",
  2291. DeviceObject, ntStatus));
  2292. break;
  2293. case IRP_MN_WAIT_WAKE:
  2294. //
  2295. // enabling the root hub for remote wakeup,
  2296. // we need to enable the HC for remote wakeup
  2297. // by posting a wakeup irp to the HC PDO.
  2298. //
  2299. // Technically the owner of the PDO for the
  2300. // HC should know if the HC signalled wakeup.
  2301. //
  2302. // make a wake irp and post it to the HCs PDO
  2303. KeAcquireSpinLock(&DeviceExtension->WaitWakeSpin,
  2304. &irql);
  2305. if (DeviceExtension->PendingWakeIrp) {
  2306. TEST_TRAP();
  2307. ntStatus = STATUS_DEVICE_BUSY;
  2308. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin, irql);
  2309. } else {
  2310. USBD_KdPrint(1, (" IRP_MJ_POWER RH pdo(%x) MN_WAIT_WAKE, pending\n",
  2311. DeviceObject));
  2312. //
  2313. // Since the host controller has only one child we don't need
  2314. // to keep track of the various PDO WaitWakes, and we can turn
  2315. // around and send it directly to the HC.
  2316. //
  2317. // Normally we would have to track the multiple children, but
  2318. // not today.
  2319. //
  2320. oldCancel = IoSetCancelRoutine(Irp, USBD_WaitWakeCancel);
  2321. ASSERT (NULL == oldCancel);
  2322. if (Irp->Cancel) {
  2323. //
  2324. // This IRP has aready been cancelled, so complete it now.
  2325. // we must clear the cancel routine before completing the IRP.
  2326. // We must release the spinlock before calling outside the
  2327. // driver.
  2328. //
  2329. IoSetCancelRoutine (Irp, NULL);
  2330. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin, irql);
  2331. ntStatus = Irp->IoStatus.Status = STATUS_CANCELLED;
  2332. } else {
  2333. //
  2334. // Keep it.
  2335. //
  2336. IoMarkIrpPending(Irp);
  2337. DeviceExtension->PendingWakeIrp = Irp;
  2338. DeviceExtension->HcWakeFlags |= HC_ENABLED_FOR_WAKEUP;
  2339. Irp->IoStatus.Information = (ULONG_PTR) DeviceExtension;
  2340. hcDeviceCapabilities = &DeviceExtension->HcDeviceCapabilities;
  2341. if (hcDeviceCapabilities->SystemWake != PowerSystemUnspecified) {
  2342. // If we are going to submit a new WW IRP to the HC below,
  2343. // then clear this flag so that we don't submit one in
  2344. // USBD_HcWaitWakeIrpCompletion.
  2345. DeviceExtension->Flags &= ~USBDFLAG_NEED_NEW_HCWAKEIRP;
  2346. }
  2347. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin, irql);
  2348. if (hcDeviceCapabilities->SystemWake != PowerSystemUnspecified) {
  2349. USBD_SubmitWaitWakeIrpToHC(DeviceExtension);
  2350. }
  2351. ntStatus = STATUS_PENDING;
  2352. goto USBD_PdoPower_Done;
  2353. }
  2354. }
  2355. USBD_KdPrint(1,
  2356. (" IRP_MJ_POWER RH pdo(%x) MN_WAIT_WAKE, status = %x complt\n",
  2357. DeviceObject, ntStatus));
  2358. break;
  2359. default:
  2360. // unknown POWER messages for the PDO created
  2361. // for the root hub
  2362. ntStatus = Irp->IoStatus.Status;
  2363. USBD_KdPrint(1, (" IRP_MJ_POWER RH pdo(%x) MN_[%d], status = %x\n",
  2364. DeviceObject, irpStack->MinorFunction, ntStatus));
  2365. }
  2366. Irp->IoStatus.Status = ntStatus;
  2367. PoStartNextPowerIrp(Irp);
  2368. USBD_IoCompleteRequest (Irp, IO_NO_INCREMENT);
  2369. USBD_PdoPower_Done:
  2370. return ntStatus;
  2371. }
  2372. NTSTATUS
  2373. USBD_PdoPnP(
  2374. PDEVICE_OBJECT DeviceObject,
  2375. PIRP Irp,
  2376. PUSBD_EXTENSION DeviceExtension
  2377. )
  2378. /*++
  2379. Routine Description:
  2380. Disptach routine for PnP Irps sent to the PDO for the root hub.
  2381. NOTE:
  2382. irps sent to the PDO are always completed by the bus driver
  2383. Arguments:
  2384. DeviceObject - Pdo for the root hub
  2385. Return Value:
  2386. None
  2387. --*/
  2388. {
  2389. PIO_STACK_LOCATION irpStack;
  2390. PDEVICE_CAPABILITIES DeviceCapabilities;
  2391. NTSTATUS ntStatus;
  2392. KIRQL irql;
  2393. PIRP idleIrp = NULL;
  2394. PIRP waitWakeIrp = NULL;
  2395. USBD_KdPrint(3, ("'enter USBD_PdoPnP\n"));
  2396. irpStack = IoGetCurrentIrpStackLocation (Irp);
  2397. ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  2398. // PNP messages for the PDO created for the root hub
  2399. switch (irpStack->MinorFunction) {
  2400. case IRP_MN_START_DEVICE:
  2401. {
  2402. PUSBD_DEVICE_DATA deviceData;
  2403. USBD_KdPrint(1, (" Starting Root hub PDO %x\n",
  2404. DeviceObject));
  2405. // If there is no RootHubPDO, fail this start.
  2406. if (!DeviceExtension->RootHubPDO) {
  2407. ntStatus = STATUS_UNSUCCESSFUL;
  2408. break;
  2409. }
  2410. //
  2411. // create the root hub on the bus
  2412. //
  2413. ntStatus = USBD_CreateDeviceX(&deviceData,
  2414. DeviceObject,
  2415. FALSE, // Not a low speed device
  2416. 8, // Roothub max endpoint
  2417. // packet size
  2418. NULL);
  2419. if (NT_SUCCESS(ntStatus)) {
  2420. ntStatus = USBD_InitializeDeviceX(deviceData,
  2421. DeviceObject,
  2422. NULL,
  2423. 0,
  2424. NULL,
  2425. 0);
  2426. }
  2427. //
  2428. // create a symbolic link for the root hub PDO
  2429. //
  2430. if (NT_SUCCESS(ntStatus)) {
  2431. DeviceExtension->RootHubDeviceData = deviceData;
  2432. USBD_SymbolicLink(TRUE, DeviceExtension);
  2433. }
  2434. }
  2435. break;
  2436. case IRP_MN_REMOVE_DEVICE:
  2437. USBD_KdPrint(1,
  2438. (" Root Hub PDO (%x) is being removed\n",
  2439. DeviceObject));
  2440. IoAcquireCancelSpinLock(&irql);
  2441. if (DeviceExtension->IdleNotificationIrp) {
  2442. idleIrp = DeviceExtension->IdleNotificationIrp;
  2443. DeviceExtension->IdleNotificationIrp = NULL;
  2444. if (idleIrp->Cancel) {
  2445. idleIrp = NULL;
  2446. }
  2447. if (idleIrp) {
  2448. IoSetCancelRoutine(idleIrp, NULL);
  2449. }
  2450. }
  2451. if (DeviceExtension->PendingWakeIrp) {
  2452. waitWakeIrp = DeviceExtension->PendingWakeIrp;
  2453. DeviceExtension->PendingWakeIrp = NULL;
  2454. DeviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  2455. // irp can no longer be cancelled
  2456. if (waitWakeIrp->Cancel || IoSetCancelRoutine(waitWakeIrp, NULL) == NULL) {
  2457. waitWakeIrp = NULL;
  2458. }
  2459. }
  2460. IoReleaseCancelSpinLock(irql);
  2461. if (idleIrp) {
  2462. idleIrp->IoStatus.Status = STATUS_CANCELLED;
  2463. IoCompleteRequest(idleIrp, IO_NO_INCREMENT);
  2464. }
  2465. if (waitWakeIrp) {
  2466. waitWakeIrp->IoStatus.Status = STATUS_CANCELLED;
  2467. PoStartNextPowerIrp(waitWakeIrp);
  2468. USBD_IoCompleteRequest(waitWakeIrp, IO_NO_INCREMENT);
  2469. }
  2470. if (DeviceExtension->RootHubDeviceData) {
  2471. USBD_RemoveDeviceX(DeviceExtension->RootHubDeviceData,
  2472. DeviceObject,
  2473. 0);
  2474. DeviceExtension->RootHubDeviceData = NULL;
  2475. USBD_SymbolicLink(FALSE, DeviceExtension);
  2476. }
  2477. //
  2478. // Ounce the removed flag is set all Irps sent to the
  2479. // PDO will be failed.
  2480. // since the HCD sets the RootHubPDO to NULL when its FDO
  2481. // is removed and this remove should happen first we should
  2482. // never see RootHubPDO == NULL
  2483. //
  2484. DeviceExtension->Flags |= USBDFLAG_PDO_REMOVED;
  2485. USBD_ASSERT(DeviceExtension->RootHubPDO != NULL);
  2486. ntStatus = STATUS_SUCCESS;
  2487. break;
  2488. case IRP_MN_STOP_DEVICE:
  2489. USBD_KdPrint(1,
  2490. (" Root Hub PDO %x is being stopped\n",
  2491. DeviceObject));
  2492. //
  2493. // Complete the Wait Wake Irp if we are stopping.
  2494. //
  2495. // We take the cancel spinlock here to ensure our cancel routine does
  2496. // not complete the Irp for us.
  2497. //
  2498. IoAcquireCancelSpinLock(&irql);
  2499. if (DeviceExtension->IdleNotificationIrp) {
  2500. idleIrp = DeviceExtension->IdleNotificationIrp;
  2501. DeviceExtension->IdleNotificationIrp = NULL;
  2502. if (idleIrp->Cancel) {
  2503. idleIrp = NULL;
  2504. }
  2505. if (idleIrp) {
  2506. IoSetCancelRoutine(idleIrp, NULL);
  2507. }
  2508. }
  2509. if (DeviceExtension->PendingWakeIrp) {
  2510. waitWakeIrp = DeviceExtension->PendingWakeIrp;
  2511. DeviceExtension->PendingWakeIrp = NULL;
  2512. DeviceExtension->HcWakeFlags &= ~HC_ENABLED_FOR_WAKEUP;
  2513. // irp can no longer be cancelled
  2514. if (waitWakeIrp->Cancel || IoSetCancelRoutine(waitWakeIrp, NULL) == NULL) {
  2515. waitWakeIrp = NULL;
  2516. }
  2517. }
  2518. IoReleaseCancelSpinLock(irql);
  2519. if (idleIrp) {
  2520. idleIrp->IoStatus.Status = STATUS_CANCELLED;
  2521. IoCompleteRequest(idleIrp, IO_NO_INCREMENT);
  2522. }
  2523. if (waitWakeIrp) {
  2524. waitWakeIrp->IoStatus.Status = STATUS_CANCELLED;
  2525. PoStartNextPowerIrp(waitWakeIrp);
  2526. USBD_IoCompleteRequest(waitWakeIrp, IO_NO_INCREMENT);
  2527. }
  2528. //
  2529. // remove the device from the bus,
  2530. // this will allow us to re-open the
  2531. // root hub endpoints (ie HC looks for address 1)
  2532. // if start failed we will have no DeviceData
  2533. if (DeviceExtension->RootHubDeviceData ) {
  2534. USBD_RemoveDeviceX(DeviceExtension->RootHubDeviceData,
  2535. DeviceObject,
  2536. 0);
  2537. DeviceExtension->RootHubDeviceData = NULL;
  2538. USBD_SymbolicLink(FALSE, DeviceExtension);
  2539. }
  2540. USBD_ASSERT(DeviceExtension->AddressList[0] == 1);
  2541. USBD_ASSERT(DeviceExtension->AddressList[1] == 0);
  2542. USBD_ASSERT(DeviceExtension->AddressList[2] == 0);
  2543. USBD_ASSERT(DeviceExtension->AddressList[3] == 0);
  2544. ntStatus = STATUS_SUCCESS;
  2545. break;
  2546. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  2547. ntStatus = STATUS_SUCCESS;
  2548. break;
  2549. case IRP_MN_QUERY_CAPABILITIES:
  2550. //
  2551. // Handle query caps for the root hub PDO
  2552. //
  2553. USBD_KdPrint(3, ("'IRP_MN_QUERY_CAPABILITIES\n"));
  2554. //
  2555. // Get the packet.
  2556. //
  2557. DeviceCapabilities=
  2558. irpStack->Parameters.DeviceCapabilities.Capabilities;
  2559. //
  2560. // The power state capabilities for the root
  2561. // hub should be the same as those of host
  2562. // controller, these were passed to USBD by
  2563. // the HCD when it registered.
  2564. //
  2565. RtlCopyMemory(DeviceCapabilities,
  2566. &DeviceExtension->RootHubDeviceCapabilities,
  2567. sizeof(*DeviceCapabilities));
  2568. //
  2569. // override these fields and
  2570. // set the root hub capabilities.
  2571. //
  2572. DeviceCapabilities->Removable=FALSE; // root hub is not removable
  2573. DeviceCapabilities->UniqueID=FALSE;
  2574. DeviceCapabilities->Address = 0;
  2575. DeviceCapabilities->UINumber = 0;
  2576. ntStatus = STATUS_SUCCESS;
  2577. break;
  2578. case IRP_MN_QUERY_ID:
  2579. USBD_KdPrint(3, ("'IOCTL_BUS_QUERY_ID\n"));
  2580. ntStatus = STATUS_SUCCESS;
  2581. switch (irpStack->Parameters.QueryId.IdType) {
  2582. case BusQueryDeviceID:
  2583. Irp->IoStatus.Information=
  2584. (ULONG_PTR)GetString(L"USB\\ROOT_HUB", FALSE);
  2585. break;
  2586. case BusQueryHardwareIDs:
  2587. Irp->IoStatus.Information=
  2588. (ULONG_PTR)GetString(L"USB\\ROOT_HUB\0USB\\OTHER_ID\0", TRUE);
  2589. break;
  2590. case BusQueryCompatibleIDs:
  2591. Irp->IoStatus.Information=0;
  2592. break;
  2593. case BusQueryInstanceID:
  2594. //
  2595. // The root HUB is instanced solely by the controller's id.
  2596. // Hence the UniqueDeviceId above.
  2597. //
  2598. Irp->IoStatus.Information=0;
  2599. break;
  2600. default:
  2601. ntStatus = Irp->IoStatus.Status;
  2602. break;
  2603. }
  2604. break;
  2605. case IRP_MN_QUERY_REMOVE_DEVICE:
  2606. case IRP_MN_QUERY_STOP_DEVICE:
  2607. case IRP_MN_CANCEL_STOP_DEVICE:
  2608. ntStatus = STATUS_SUCCESS;
  2609. break;
  2610. case IRP_MN_QUERY_INTERFACE:
  2611. ntStatus = USBD_GetBusInterface(DeviceExtension->RootHubPDO,
  2612. Irp);
  2613. break;
  2614. case IRP_MN_QUERY_BUS_INFORMATION:
  2615. {
  2616. // return the standard USB GUID
  2617. PPNP_BUS_INFORMATION busInfo;
  2618. busInfo = ExAllocatePoolWithTag(PagedPool,
  2619. sizeof(PNP_BUS_INFORMATION),
  2620. USBD_TAG);
  2621. if (busInfo == NULL) {
  2622. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2623. } else {
  2624. busInfo->BusTypeGuid = GUID_BUS_TYPE_USB;
  2625. busInfo->LegacyBusType = PNPBus;
  2626. busInfo->BusNumber = 0;
  2627. Irp->IoStatus.Information = (ULONG_PTR) busInfo;
  2628. ntStatus = STATUS_SUCCESS;
  2629. }
  2630. }
  2631. break;
  2632. case IRP_MN_QUERY_DEVICE_RELATIONS:
  2633. USBD_KdPrint(1,
  2634. (" IRP_MN_QUERY_DEVICE_RELATIONS (PDO) %x %x\n",
  2635. DeviceObject,
  2636. irpStack->Parameters.QueryDeviceRelations.Type));
  2637. if (irpStack->Parameters.QueryDeviceRelations.Type ==
  2638. TargetDeviceRelation) {
  2639. PDEVICE_RELATIONS deviceRelations = NULL;
  2640. deviceRelations =
  2641. ExAllocatePoolWithTag(PagedPool, sizeof(*deviceRelations),
  2642. USBD_TAG);
  2643. if (deviceRelations == NULL) {
  2644. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2645. } else if (DeviceExtension->RootHubPDO == NULL) {
  2646. deviceRelations->Count = 0;
  2647. ntStatus = STATUS_SUCCESS;
  2648. } else {
  2649. deviceRelations->Count = 1;
  2650. ObReferenceObject(DeviceExtension->RootHubPDO);
  2651. deviceRelations->Objects[0] =
  2652. DeviceExtension->RootHubPDO;
  2653. ntStatus = STATUS_SUCCESS;
  2654. }
  2655. Irp->IoStatus.Information=(ULONG_PTR) deviceRelations;
  2656. USBD_KdPrint(1, (" TargetDeviceRelation to Root Hub PDO - complt\n"));
  2657. } else {
  2658. ntStatus = Irp->IoStatus.Status;
  2659. }
  2660. break;
  2661. default:
  2662. USBD_KdPrint(1, (" PnP IOCTL(%d) to root hub PDO not handled\n",
  2663. irpStack->MinorFunction));
  2664. ntStatus = Irp->IoStatus.Status;
  2665. } /* switch, PNP minor function */
  2666. Irp->IoStatus.Status = ntStatus;
  2667. USBD_IoCompleteRequest (Irp,
  2668. IO_NO_INCREMENT);
  2669. return ntStatus;
  2670. }
  2671. NTSTATUS
  2672. USBD_DeferPoRequestCompletion(
  2673. IN PDEVICE_OBJECT DeviceObject,
  2674. IN UCHAR MinorFunction,
  2675. IN POWER_STATE DeviceState,
  2676. IN PVOID Context,
  2677. IN PIO_STATUS_BLOCK IoStatus
  2678. )
  2679. /*++
  2680. Routine Description:
  2681. This routine is called when the port driver completes an IRP.
  2682. Arguments:
  2683. DeviceObject - Pointer to the device object for the class device.
  2684. SetState - TRUE for set, FALSE for query.
  2685. DevicePowerState - The Dx that we are in/tagetted.
  2686. Context - Driver defined context, in this case the original power Irp.
  2687. IoStatus - The status of the IRP.
  2688. Return Value:
  2689. The function value is the final status from the operation.
  2690. --*/
  2691. {
  2692. PIRP irp;
  2693. PUSBD_EXTENSION deviceExtension = Context;
  2694. NTSTATUS ntStatus = IoStatus->Status;
  2695. irp = deviceExtension->PowerIrp;
  2696. IoCopyCurrentIrpStackLocationToNext(irp);
  2697. PoStartNextPowerIrp(irp);
  2698. PoCallDriver(deviceExtension->HcdTopOfPdoStackDeviceObject,
  2699. irp);
  2700. return ntStatus;
  2701. }
  2702. VOID
  2703. USBD_IdleNotificationCancelRoutine(
  2704. IN PDEVICE_OBJECT DeviceObject,
  2705. IN PIRP Irp
  2706. )
  2707. /*++
  2708. Routine Description:
  2709. Arguments:
  2710. DeviceObject -
  2711. Irp - Power Irp.
  2712. Return Value:
  2713. --*/
  2714. {
  2715. PUSBD_EXTENSION deviceExtension;
  2716. deviceExtension = DeviceObject->DeviceExtension;
  2717. deviceExtension->IdleNotificationIrp = NULL;
  2718. IoReleaseCancelSpinLock(Irp->CancelIrql);
  2719. Irp->IoStatus.Status = STATUS_CANCELLED;
  2720. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2721. }
  2722. NTSTATUS
  2723. USBD_IdleNotificationRequest(
  2724. IN PUSBD_EXTENSION DeviceExtension,
  2725. IN PIRP Irp
  2726. )
  2727. /* ++
  2728. *
  2729. * Description:
  2730. *
  2731. * This function handles a request by a USB client driver (in this case
  2732. * USBHUB) to tell us that the device wants to idle (selective suspend).
  2733. *
  2734. * Arguments:
  2735. *
  2736. * DeviceExtension - the PDO extension
  2737. * Irp - the request packet
  2738. *
  2739. * Return:
  2740. *
  2741. * NTSTATUS
  2742. *
  2743. * -- */
  2744. {
  2745. PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
  2746. NTSTATUS ntStatus = STATUS_PENDING;
  2747. KIRQL irql;
  2748. PIRP idleIrp;
  2749. IoAcquireCancelSpinLock(&irql);
  2750. if (DeviceExtension->IdleNotificationIrp != NULL) {
  2751. IoReleaseCancelSpinLock(irql);
  2752. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  2753. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2754. ntStatus = STATUS_DEVICE_BUSY;
  2755. goto USBD_IdleNotificationRequestDone;
  2756. } else if (Irp->Cancel) {
  2757. IoReleaseCancelSpinLock(irql);
  2758. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  2759. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2760. ntStatus = STATUS_CANCELLED;
  2761. goto USBD_IdleNotificationRequestDone;
  2762. }
  2763. idleCallbackInfo = (PUSB_IDLE_CALLBACK_INFO)
  2764. IoGetCurrentIrpStackLocation(Irp)->\
  2765. Parameters.DeviceIoControl.Type3InputBuffer;
  2766. USBD_ASSERT(idleCallbackInfo && idleCallbackInfo->IdleCallback);
  2767. if (!idleCallbackInfo || !idleCallbackInfo->IdleCallback) {
  2768. IoReleaseCancelSpinLock(irql);
  2769. Irp->IoStatus.Status = STATUS_NO_CALLBACK_ACTIVE;
  2770. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2771. ntStatus = STATUS_NO_CALLBACK_ACTIVE;
  2772. goto USBD_IdleNotificationRequestDone;
  2773. }
  2774. DeviceExtension->IdleNotificationIrp = Irp;
  2775. IoSetCancelRoutine(Irp, USBD_IdleNotificationCancelRoutine);
  2776. IoReleaseCancelSpinLock(irql);
  2777. //
  2778. // Call the idle function now.
  2779. //
  2780. if (idleCallbackInfo && idleCallbackInfo->IdleCallback) {
  2781. // Here we actually call the driver's callback routine,
  2782. // telling the driver that it is OK to suspend their
  2783. // device now.
  2784. idleCallbackInfo->IdleCallback(idleCallbackInfo->IdleContext);
  2785. }
  2786. USBD_IdleNotificationRequestDone:
  2787. return ntStatus;
  2788. }
  2789. NTSTATUS
  2790. USBD_PdoDispatch(
  2791. PDEVICE_OBJECT DeviceObject,
  2792. PIRP Irp,
  2793. PUSBD_EXTENSION DeviceExtension,
  2794. PBOOLEAN IrpNeedsCompletion
  2795. )
  2796. /*++
  2797. Routine Description:
  2798. Disptach routine for Irps sent to the PDO for the root hub.
  2799. NOTE:
  2800. irps sent to the PDO are always completed by the bus driver
  2801. Arguments:
  2802. Return Value:
  2803. None
  2804. --*/
  2805. {
  2806. PIO_STACK_LOCATION irpStack;
  2807. NTSTATUS ntStatus;
  2808. USBD_KdPrint(3, ("'enter USBD_PdoDispatch\n"));
  2809. *IrpNeedsCompletion = FALSE;
  2810. irpStack = IoGetCurrentIrpStackLocation (Irp);
  2811. switch (irpStack->MajorFunction) {
  2812. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  2813. switch(irpStack->Parameters.DeviceIoControl.IoControlCode) {
  2814. case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
  2815. USBD_KdPrint(3, ("'IOCTL_INTERNAL_USB_GET_HUB_COUNT\n"));
  2816. {
  2817. PULONG count;
  2818. //
  2819. // bump the count and complete the Irp
  2820. //
  2821. count = irpStack->Parameters.Others.Argument1;
  2822. ASSERT(count != NULL);
  2823. (*count)++;
  2824. ntStatus = STATUS_SUCCESS;
  2825. }
  2826. break;
  2827. case IOCTL_INTERNAL_USB_GET_BUS_INFO:
  2828. {
  2829. PUSB_BUS_NOTIFICATION busInfo;
  2830. USBD_KdPrint(0,
  2831. ("'WARNING: Driver using obsolete IOCTL (IOCTL_INTERNAL_USB_GET_BUS_INFO) - get JD\n"));
  2832. busInfo = irpStack->Parameters.Others.Argument1;
  2833. // bw in bit times (bits/ms)
  2834. busInfo->TotalBandwidth = 12000;
  2835. busInfo->ConsumedBandwidth =
  2836. DeviceExtension->HcdGetConsumedBW(
  2837. DeviceExtension->HcdDeviceObject);
  2838. busInfo->ControllerNameLength =
  2839. DeviceExtension->DeviceLinkUnicodeString.Length;
  2840. }
  2841. ntStatus = STATUS_SUCCESS;
  2842. break;
  2843. case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME:
  2844. {
  2845. PUSB_HUB_NAME name;
  2846. ULONG length;
  2847. USBD_KdPrint(1, ("'IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n"));
  2848. name = (PUSB_HUB_NAME) irpStack->Parameters.Others.Argument1;
  2849. length = PtrToUlong( irpStack->Parameters.Others.Argument2 );
  2850. USBD_KdPrint(1, ("'length = %d %x\n", length, &DeviceExtension->DeviceLinkUnicodeString));
  2851. name->ActualLength = DeviceExtension->DeviceLinkUnicodeString.Length;
  2852. if (length > DeviceExtension->DeviceLinkUnicodeString.Length) {
  2853. length = DeviceExtension->DeviceLinkUnicodeString.Length;
  2854. }
  2855. RtlCopyMemory(&name->HubName[0],
  2856. &DeviceExtension->DeviceLinkUnicodeString.Buffer[0],
  2857. length);
  2858. }
  2859. ntStatus = STATUS_SUCCESS;
  2860. break;
  2861. case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
  2862. USBD_KdPrint(3, ("'IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n"));
  2863. {
  2864. PDEVICE_OBJECT *rootHubPdo, *hcdTopOfStackDeviceObject;
  2865. rootHubPdo = irpStack->Parameters.Others.Argument1;
  2866. hcdTopOfStackDeviceObject =
  2867. irpStack->Parameters.Others.Argument2;
  2868. ASSERT(hcdTopOfStackDeviceObject != NULL);
  2869. ASSERT(rootHubPdo != NULL);
  2870. *rootHubPdo = DeviceExtension->RootHubPDO;
  2871. *hcdTopOfStackDeviceObject =
  2872. DeviceExtension->HcdTopOfStackDeviceObject;
  2873. ntStatus = STATUS_SUCCESS;
  2874. }
  2875. break;
  2876. case IOCTL_INTERNAL_USB_GET_HUB_NAME:
  2877. USBD_KdPrint(3, ("'IOCTL_INTERNAL_USB_GET_HUB_NAME\n"));
  2878. ntStatus = USBD_GetHubName(DeviceExtension, Irp);
  2879. break;
  2880. case IOCTL_INTERNAL_USB_SUBMIT_URB:
  2881. USBD_KdPrint(3,
  2882. ("'IOCTL_INTERNAL_USB_SUBMIT_URB to root hub PDO\n"));
  2883. // pass these along to the bus
  2884. IoCopyCurrentIrpStackLocationToNext(Irp);
  2885. ntStatus = IoCallDriver(DeviceExtension->HcdDeviceObject, Irp);
  2886. // this is a special case -- we tell the HCD not to complete it
  2887. // because he will see it agian passed to his FDO
  2888. //
  2889. // the only code to pass thru this case should be urb requests
  2890. // submitted to the root hub.
  2891. goto USBD_PdoDispatch_Done;
  2892. break;
  2893. case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
  2894. if (DeviceExtension->IsPIIX3or4 && !DeviceExtension->WakeSupported) {
  2895. USBD_KdPrint(1, ("'Idle request, HC can NOT idle, fail.\n"));
  2896. ntStatus = STATUS_NOT_SUPPORTED;
  2897. } else {
  2898. USBD_KdPrint(1, ("'Idle request, HC can idle.\n"));
  2899. ntStatus = USBD_IdleNotificationRequest(DeviceExtension, Irp);
  2900. goto USBD_PdoDispatch_Done; // Don't complete the IRP.
  2901. }
  2902. break;
  2903. default:
  2904. ntStatus = STATUS_INVALID_PARAMETER;
  2905. USBD_KdPrint(1,
  2906. ("Warning: Invalid IRP_MJ_INTERNAL_DEVICE_CONTROL passed to USBD\n"));
  2907. } // switch, ioControlCode
  2908. break;
  2909. case IRP_MJ_PNP:
  2910. // thie function will complete request if needed
  2911. ntStatus = USBD_PdoPnP(DeviceObject,
  2912. Irp,
  2913. DeviceExtension);
  2914. goto USBD_PdoDispatch_Done;
  2915. break;
  2916. case IRP_MJ_POWER:
  2917. // thie function will complete request if needed
  2918. ntStatus = USBD_PdoPower(DeviceObject,
  2919. Irp,
  2920. DeviceExtension);
  2921. goto USBD_PdoDispatch_Done;
  2922. break;
  2923. case IRP_MJ_SYSTEM_CONTROL:
  2924. USBD_KdPrint(3, ("'HC PDO IRP_MJ_SYSTEM_CONTROL\n"));
  2925. default:
  2926. ntStatus = STATUS_NOT_SUPPORTED;
  2927. } /* switch, irpStack->MajorFunction */
  2928. Irp->IoStatus.Status = ntStatus;
  2929. USBD_IoCompleteRequest (Irp,
  2930. IO_NO_INCREMENT);
  2931. USBD_PdoDispatch_Done:
  2932. USBD_KdPrint(3, ("'exit USBD_PdoDispatch, ntStatus = %x\n", ntStatus));
  2933. return ntStatus;
  2934. }
  2935. NTSTATUS
  2936. USBD_PnPIrp_Complete(
  2937. IN PDEVICE_OBJECT DeviceObject,
  2938. IN PIRP Irp,
  2939. IN PVOID Context
  2940. )
  2941. /*++
  2942. Routine Description:
  2943. This routine is called when the port driver completes an IRP.
  2944. Arguments:
  2945. DeviceObject - Pointer to the device object for the class device.
  2946. Irp - Irp completed.
  2947. Context - Driver defined context.
  2948. Return Value:
  2949. The function value is the final status from the operation.
  2950. --*/
  2951. {
  2952. NTSTATUS ntStatus = STATUS_SUCCESS;
  2953. NTSTATUS irpStatus;
  2954. PIO_STACK_LOCATION irpStack;
  2955. PUSBD_EXTENSION deviceExtension;
  2956. USBD_KdPrint(3, ("'enter USBD_PnPIrp_Complete\n"));
  2957. deviceExtension = (PUSBD_EXTENSION) Context;
  2958. irpStack = IoGetCurrentIrpStackLocation (Irp);
  2959. irpStatus = Irp->IoStatus.Status;
  2960. USBD_ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  2961. USBD_ASSERT(irpStack->MinorFunction == IRP_MN_START_DEVICE);
  2962. USBD_KdPrint(3, ("'IRP_MN_START_DEVICE (fdo), completion routine\n"));
  2963. // signal the start device dispatch to finsh
  2964. KeSetEvent(&deviceExtension->PnpStartEvent,
  2965. 1,
  2966. FALSE);
  2967. // defer completion
  2968. ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
  2969. USBD_KdPrint(3, ("'exit USBD_PnPIrp_Complete %x\n", irpStatus));
  2970. return ntStatus;
  2971. }
  2972. NTSTATUS
  2973. USBD_FdoPower(
  2974. IN PDEVICE_OBJECT DeviceObject,
  2975. IN PIRP Irp,
  2976. IN PUSBD_EXTENSION DeviceExtension,
  2977. IN PBOOLEAN IrpNeedsCompletion
  2978. )
  2979. /*++
  2980. Routine Description:
  2981. Process the Power IRPs sent to the FDO for the host controller.
  2982. Power States for the USB host controller
  2983. D0 - On.
  2984. D1/D2 - Suspend.
  2985. D3 - Off.
  2986. Arguments:
  2987. DeviceObject - pointer to a hcd device object (FDO)
  2988. Irp - pointer to an I/O Request Packet
  2989. Return Value:
  2990. NT status code
  2991. --*/
  2992. {
  2993. PIO_STACK_LOCATION irpStack;
  2994. NTSTATUS ntStatus = STATUS_SUCCESS;
  2995. BOOLEAN hookIt = FALSE;
  2996. BOOLEAN biosHandback = FALSE;
  2997. KIRQL irql;
  2998. USBD_KdPrint(3, ("'HC FDO IRP_MJ_POWER\n"));
  2999. irpStack = IoGetCurrentIrpStackLocation (Irp);
  3000. *IrpNeedsCompletion = FALSE;
  3001. switch (irpStack->MinorFunction) {
  3002. case IRP_MN_WAIT_WAKE:
  3003. USBD_KdPrint(3, ("'IRP_MN_WAIT_WAKE\n"));
  3004. //
  3005. // someone is enabling us for wakeup
  3006. //
  3007. // pass this on to our PDO
  3008. goto USBD_FdoPowerPassIrp;
  3009. break;
  3010. case IRP_MN_SET_POWER:
  3011. {
  3012. switch (irpStack->Parameters.Power.Type) {
  3013. case SystemPowerState:
  3014. {
  3015. POWER_STATE powerState;
  3016. USBD_KdPrint(1,
  3017. (" IRP_MJ_POWER HC fdo(%x) MN_SET_POWER(SystemPowerState S%x)\n",
  3018. DeviceObject, irpStack->Parameters.Power.State.SystemState - 1));
  3019. switch (irpStack->Parameters.Power.State.SystemState) {
  3020. case PowerSystemWorking:
  3021. //
  3022. // go to 'ON'
  3023. //
  3024. powerState.DeviceState = PowerDeviceD0;
  3025. break;
  3026. case PowerSystemShutdown:
  3027. //
  3028. // Shutdown -- if we need to hand contol back to HC
  3029. // then we finish here
  3030. //
  3031. USBD_KdPrint(1, (" Shutdown HC Detected\n"));
  3032. // flag should only be true if we
  3033. // shutdown to DOS (ie Win98)
  3034. ntStatus =
  3035. DeviceExtension->HcdSetDevicePowerState(
  3036. DeviceObject,
  3037. Irp,
  3038. 0);
  3039. biosHandback = TRUE;
  3040. DeviceExtension->Flags |= USBDFLAG_HCD_SHUTDOWN;
  3041. powerState.DeviceState = PowerDeviceD3;
  3042. break;
  3043. case PowerSystemHibernate:
  3044. USBD_KdPrint(1, (" Hibernate HC Detected\n"));
  3045. powerState.DeviceState = PowerDeviceD3;
  3046. break;
  3047. case PowerSystemSleeping1:
  3048. case PowerSystemSleeping2:
  3049. case PowerSystemSleeping3:
  3050. //
  3051. // Let HCD know there is a suspend coming.
  3052. //
  3053. USBD_KdPrint(1, (" Suspend HC Detected\n"));
  3054. ntStatus =
  3055. DeviceExtension->HcdSetDevicePowerState(
  3056. DeviceObject,
  3057. Irp,
  3058. 0);
  3059. // Fall through
  3060. default:
  3061. //
  3062. // our policy is to enter D3 unless we are enabled for
  3063. // remote wakeup
  3064. //
  3065. if (DeviceExtension->HcWakeFlags & HC_ENABLED_FOR_WAKEUP) {
  3066. SYSTEM_POWER_STATE requestedSystemState;
  3067. requestedSystemState =
  3068. irpStack->Parameters.Power.State.SystemState;
  3069. //
  3070. // based on the system power state
  3071. // request a setting to the appropriate
  3072. // Dx state.
  3073. //
  3074. powerState.DeviceState =
  3075. DeviceExtension->HcDeviceCapabilities.DeviceState[
  3076. requestedSystemState];
  3077. USBD_KdPrint(1, (" Requested HC State before fixup is S%x -> D%d\n",
  3078. requestedSystemState - 1,
  3079. powerState.DeviceState - 1));
  3080. //
  3081. // This table is created by PDO of the PCI driver and
  3082. // describes what the PCI driver can do for us.
  3083. // It is entirely possible that when the controller is in
  3084. // the D3 state that we can wake the system.
  3085. //
  3086. // It is also entirely possible that this table might not
  3087. // support a D state at the current S state.
  3088. //
  3089. // All of the usb children support a D state for every S
  3090. // state. (We patched it up just that way when we gave
  3091. // the capablilities to our PDO child. However, the host
  3092. // controller might not have one. So if this is
  3093. // unsupported, then we need to change it do D3.
  3094. //
  3095. if (requestedSystemState > DeviceExtension->HcDeviceCapabilities.SystemWake &&
  3096. PowerDeviceUnspecified == powerState.DeviceState) {
  3097. powerState.DeviceState = PowerDeviceD3;
  3098. } else {
  3099. USBD_ASSERT(powerState.DeviceState != PowerDeviceUnspecified);
  3100. }
  3101. } else {
  3102. //
  3103. // wakeup not enabled, just go in to the 'OFF' state.
  3104. //
  3105. USBD_KdPrint(1, ("HC not enabled for wakeup, goto D3.\n"));
  3106. powerState.DeviceState = PowerDeviceD3;
  3107. }
  3108. } //irpStack->Parameters.Power.State.SystemState
  3109. USBD_KdPrint(1,
  3110. (" Requested HC State after fixup is D%d\n", powerState.DeviceState-1));
  3111. //
  3112. // are we already in this state?
  3113. //
  3114. //
  3115. // Note: if we get a D3 request before we are started
  3116. // we don't need to pass the irp down to turn us off
  3117. // we consider the controller initially off until we
  3118. // get start.
  3119. //
  3120. if (!biosHandback &&
  3121. powerState.DeviceState !=
  3122. DeviceExtension->HcCurrentDevicePowerState) {
  3123. if (powerState.DeviceState == PowerDeviceD0) {
  3124. KeAcquireSpinLock(&DeviceExtension->WaitWakeSpin,
  3125. &irql);
  3126. // see if we need to cancel a wake irp
  3127. // in the HC
  3128. if (DeviceExtension->HcWakeIrp) {
  3129. PIRP hcwakeirp;
  3130. hcwakeirp = DeviceExtension->HcWakeIrp;
  3131. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  3132. irql);
  3133. USBD_KdPrint(1, ("USBD_FdoPower, Set D0: Canceling Wake Irp (%x) on HC PDO\n", hcwakeirp));
  3134. IoCancelIrp(hcwakeirp);
  3135. } else {
  3136. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  3137. irql);
  3138. }
  3139. }
  3140. // No,
  3141. // now allocate another irp and use PoCallDriver
  3142. // to send it to ourselves
  3143. IoMarkIrpPending(Irp);
  3144. DeviceExtension->PowerIrp = Irp;
  3145. USBD_KdPrint(1,
  3146. (" Requesting HC State is D%d\n", powerState.DeviceState-1));
  3147. ntStatus =
  3148. PoRequestPowerIrp(DeviceExtension->
  3149. HcdPhysicalDeviceObject,
  3150. IRP_MN_SET_POWER,
  3151. powerState,
  3152. USBD_DeferPoRequestCompletion,
  3153. DeviceExtension,
  3154. NULL);
  3155. USBD_KdPrint(3, ("'PoRequestPowerIrp returned %x\n",
  3156. ntStatus));
  3157. } else {
  3158. //
  3159. // now complete the original request
  3160. //
  3161. IoCopyCurrentIrpStackLocationToNext(Irp);
  3162. PoStartNextPowerIrp(Irp);
  3163. ntStatus =
  3164. PoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3165. Irp);
  3166. }
  3167. }
  3168. break;
  3169. case DevicePowerState:
  3170. USBD_KdPrint(1,
  3171. (" IRP_MJ_POWER HC fdo(%x) MN_SET_POWER(DevicePowerState D%x)\n",
  3172. DeviceObject,
  3173. irpStack->Parameters.Power.State.DeviceState - 1));
  3174. //
  3175. // Copy parameters now in case the HcdSetDevicePowerState
  3176. // function sets a completion routine.
  3177. //
  3178. IoCopyCurrentIrpStackLocationToNext(Irp);
  3179. // If the HC is already in the requested power state
  3180. // then don't call the HcdSetDevicePowerState function.
  3181. // NOTE:
  3182. // if the HC is not started the power state should be D3
  3183. // we will ignore any requests from the OS to put
  3184. // it in any other state
  3185. #if DBG
  3186. if (!(DeviceExtension->Flags & USBDFLAG_HCD_STARTED) &&
  3187. irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0) {
  3188. USBD_KdPrint(1,
  3189. (" OS requesting to power up a STOPPED device\n"));
  3190. }
  3191. #endif
  3192. if (DeviceExtension->HcCurrentDevicePowerState !=
  3193. irpStack->Parameters.Power.State.DeviceState &&
  3194. (DeviceExtension->Flags & USBDFLAG_HCD_STARTED)) {
  3195. ntStatus =
  3196. DeviceExtension->HcdSetDevicePowerState(
  3197. DeviceObject,
  3198. Irp,
  3199. irpStack->Parameters.Power.State.DeviceState);
  3200. DeviceExtension->HcCurrentDevicePowerState =
  3201. irpStack->Parameters.Power.State.DeviceState;
  3202. }
  3203. PoStartNextPowerIrp(Irp);
  3204. ntStatus =
  3205. PoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3206. Irp);
  3207. break;
  3208. } /* case irpStack->Parameters.Power.Type */
  3209. }
  3210. break; /* IRP_MN_SET_POWER */
  3211. case IRP_MN_QUERY_POWER:
  3212. USBD_KdPrint(1,
  3213. (" IRP_MJ_POWER HC fdo(%x) MN_QUERY_POWER\n",
  3214. DeviceObject));
  3215. // IrpAssert: Set IRP status before passing this IRP down.
  3216. Irp->IoStatus.Status = STATUS_SUCCESS;
  3217. //
  3218. // according to busdd QUERY_POWER messages are not
  3219. // sent down the driver stack
  3220. //
  3221. IoCopyCurrentIrpStackLocationToNext(Irp);
  3222. PoStartNextPowerIrp(Irp);
  3223. ntStatus =
  3224. PoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3225. Irp);
  3226. break; /* IRP_MN_QUERY_POWER */
  3227. default:
  3228. USBD_FdoPowerPassIrp:
  3229. USBD_KdPrint(1,
  3230. (" IRP_MJ_POWER fdo(%x) MN_%d\n",
  3231. DeviceObject, irpStack->MinorFunction));
  3232. //
  3233. // All unhandled PnP messages are passed on to the PDO
  3234. //
  3235. IoCopyCurrentIrpStackLocationToNext(Irp);
  3236. //
  3237. // All PNP_POWER POWER messages get passed to TopOfStackDeviceObject
  3238. // and some are handled in the completion routine
  3239. //
  3240. // pass on to our PDO
  3241. PoStartNextPowerIrp(Irp);
  3242. ntStatus =
  3243. PoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3244. Irp);
  3245. } /* irpStack->MinorFunction */
  3246. USBD_KdPrint(3, ("'exit USBD_FdoPower 0x%x\n", ntStatus));
  3247. return ntStatus;
  3248. }
  3249. NTSTATUS
  3250. USBD_GetHubName(
  3251. PUSBD_EXTENSION DeviceExtension,
  3252. PIRP Irp
  3253. )
  3254. {
  3255. PUNICODE_STRING deviceNameUnicodeString;
  3256. NTSTATUS status = STATUS_SUCCESS;
  3257. PUSB_ROOT_HUB_NAME outputBuffer;
  3258. ULONG outputBufferLength;
  3259. PIO_STACK_LOCATION irpStack;
  3260. irpStack = IoGetCurrentIrpStackLocation (Irp);
  3261. outputBufferLength =
  3262. irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  3263. outputBuffer = Irp->AssociatedIrp.SystemBuffer;
  3264. deviceNameUnicodeString =
  3265. &DeviceExtension->RootHubSymbolicLinkName;
  3266. if (NT_SUCCESS(status)) {
  3267. //
  3268. // make sure there is enough room for the length,
  3269. // string and the NULL
  3270. //
  3271. ULONG length, offset=0;
  3272. WCHAR *pwch;
  3273. // assuming the string is \n\name strip of '\n\' where
  3274. // n is zero or more chars
  3275. pwch = &deviceNameUnicodeString->Buffer[0];
  3276. // Under NT, if the controller is banged out in DeviceManager,
  3277. // this will be NULL.
  3278. if (!pwch) {
  3279. status = STATUS_UNSUCCESSFUL;
  3280. goto USBD_GetHubNameExit;
  3281. }
  3282. USBD_ASSERT(*pwch == '\\');
  3283. if (*pwch == '\\') {
  3284. pwch++;
  3285. while (*pwch != '\\' && *pwch) {
  3286. pwch++;
  3287. }
  3288. USBD_ASSERT(*pwch == '\\');
  3289. if (*pwch == '\\') {
  3290. pwch++;
  3291. }
  3292. offset = (ULONG)((PUCHAR)pwch -
  3293. (PUCHAR)&deviceNameUnicodeString->Buffer[0]);
  3294. }
  3295. length = deviceNameUnicodeString->Length - offset;
  3296. RtlZeroMemory(outputBuffer, outputBufferLength);
  3297. if (outputBufferLength >= length +
  3298. sizeof(USB_ROOT_HUB_NAME)) {
  3299. RtlCopyMemory(&outputBuffer->RootHubName[0],
  3300. &deviceNameUnicodeString->Buffer[offset/2],
  3301. length);
  3302. Irp->IoStatus.Information = length+
  3303. sizeof(USB_ROOT_HUB_NAME);
  3304. outputBuffer->ActualLength = (ULONG)Irp->IoStatus.Information;
  3305. status = STATUS_SUCCESS;
  3306. } else {
  3307. if (outputBufferLength >= sizeof(USB_ROOT_HUB_NAME)) {
  3308. outputBuffer->ActualLength =
  3309. length + sizeof(USB_ROOT_HUB_NAME);
  3310. Irp->IoStatus.Information =
  3311. sizeof(ULONG);
  3312. status = STATUS_SUCCESS;
  3313. } else {
  3314. status = STATUS_BUFFER_TOO_SMALL;
  3315. }
  3316. }
  3317. }
  3318. USBD_GetHubNameExit:
  3319. return status;
  3320. }
  3321. #ifdef DRM_SUPPORT
  3322. /*****************************************************************************
  3323. * USBC_FdoSetContentId
  3324. *****************************************************************************
  3325. *
  3326. */
  3327. NTSTATUS
  3328. USBD_FdoSetContentId
  3329. (
  3330. IN PIRP irp,
  3331. IN PKSP_DRMAUDIOSTREAM_CONTENTID pKsProperty,
  3332. IN PKSDRMAUDIOSTREAM_CONTENTID pvData
  3333. )
  3334. {
  3335. USBD_PIPE_HANDLE hPipe;
  3336. NTSTATUS status;
  3337. PAGED_CODE();
  3338. ASSERT(irp);
  3339. ASSERT(pKsProperty);
  3340. ASSERT(pvData);
  3341. status = STATUS_SUCCESS;
  3342. hPipe = pKsProperty->Context;
  3343. // ContentId = pvData->ContentId;
  3344. ASSERT(USBD_ValidatePipe(hPipe));
  3345. // If this driver sents content anywhere, then it should advise DRM. E.g.:
  3346. // status = pKsProperty->DrmForwardContentToDeviceObject(ContentId, DeviceObject, Context);
  3347. return status;
  3348. }
  3349. #endif
  3350. NTSTATUS
  3351. USBD_FdoDispatch(
  3352. PDEVICE_OBJECT DeviceObject,
  3353. PIRP Irp,
  3354. PUSBD_EXTENSION DeviceExtension,
  3355. PBOOLEAN IrpNeedsCompletion
  3356. )
  3357. /*++
  3358. Routine Description:
  3359. Disptach routine for Irps sent to the FDO for the host controller. some
  3360. Irps re handled by USBD, most are handled by the host controller driver.
  3361. Arguments:
  3362. Return Value:
  3363. None
  3364. --*/
  3365. {
  3366. PIO_STACK_LOCATION irpStack;
  3367. PDEVICE_RELATIONS DeviceRelations = NULL;
  3368. NTSTATUS ntStatus = STATUS_SUCCESS;
  3369. PURB urb;
  3370. KIRQL irql;
  3371. USBD_KdPrint(3, ("'enter USBD_FdoDispatch\n"));
  3372. irpStack = IoGetCurrentIrpStackLocation (Irp);
  3373. switch (irpStack->MajorFunction) {
  3374. case IRP_MJ_DEVICE_CONTROL:
  3375. USBD_KdPrint(3, ("'IRP_MJ_DEVICE_CONTROL\n"));
  3376. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  3377. #ifdef DRM_SUPPORT
  3378. case IOCTL_KS_PROPERTY:
  3379. USBD_KdPrint(1, ("'IOCTL_KS_PROPERTY\n"));
  3380. ntStatus = KsPropertyHandleDrmSetContentId(Irp, USBD_FdoSetContentId);
  3381. Irp->IoStatus.Status = ntStatus;
  3382. if (NT_SUCCESS(ntStatus) || (STATUS_PROPSET_NOT_FOUND == ntStatus)) {
  3383. *IrpNeedsCompletion = TRUE;
  3384. } else {
  3385. *IrpNeedsCompletion = FALSE;
  3386. USBD_IoCompleteRequest(Irp, IO_NO_INCREMENT);
  3387. }
  3388. break;
  3389. #endif
  3390. case IOCTL_USB_DIAGNOSTIC_MODE_ON:
  3391. DeviceExtension->DiagnosticMode = TRUE;
  3392. *IrpNeedsCompletion = FALSE;
  3393. USBD_KdPrint(1, ("'IOCTL_USB_DIAGNOSTIC_MODE_ON\n"));
  3394. ntStatus =
  3395. Irp->IoStatus.Status = STATUS_SUCCESS;
  3396. USBD_IoCompleteRequest (Irp,
  3397. IO_NO_INCREMENT);
  3398. break;
  3399. case IOCTL_USB_DIAGNOSTIC_MODE_OFF:
  3400. DeviceExtension->DiagnosticMode = FALSE;
  3401. *IrpNeedsCompletion = FALSE;
  3402. USBD_KdPrint(1, ("'IOCTL_USB_DIAGNOSTIC_MODE_OFF\n"));
  3403. ntStatus =
  3404. Irp->IoStatus.Status = STATUS_SUCCESS;
  3405. USBD_IoCompleteRequest (Irp,
  3406. IO_NO_INCREMENT);
  3407. break;
  3408. case IOCTL_USB_DIAG_IGNORE_HUBS_ON:
  3409. DeviceExtension->DiagIgnoreHubs = TRUE;
  3410. *IrpNeedsCompletion = FALSE;
  3411. USBD_KdPrint(1, ("'IOCTL_USB_DIAG_IGNORE_HUBS_ON\n"));
  3412. ntStatus =
  3413. Irp->IoStatus.Status = STATUS_SUCCESS;
  3414. USBD_IoCompleteRequest (Irp,
  3415. IO_NO_INCREMENT);
  3416. break;
  3417. case IOCTL_USB_DIAG_IGNORE_HUBS_OFF:
  3418. DeviceExtension->DiagIgnoreHubs = FALSE;
  3419. *IrpNeedsCompletion = FALSE;
  3420. USBD_KdPrint(1, ("'IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n"));
  3421. ntStatus =
  3422. Irp->IoStatus.Status = STATUS_SUCCESS;
  3423. USBD_IoCompleteRequest (Irp,
  3424. IO_NO_INCREMENT);
  3425. break;
  3426. case IOCTL_GET_HCD_DRIVERKEY_NAME:
  3427. *IrpNeedsCompletion = FALSE;
  3428. USBD_KdPrint(3, ("'IOCTL_GET_HCD_DRIVERKEY_NAME\n"));
  3429. {
  3430. PIO_STACK_LOCATION ioStack;
  3431. PUSB_HCD_DRIVERKEY_NAME outputBuffer;
  3432. ULONG outputBufferLength, length;
  3433. ULONG adjustedDriverKeyNameSize;
  3434. //
  3435. // Get a pointer to the current location in the Irp. This is where
  3436. // the function codes and parameters are located.
  3437. //
  3438. ioStack = IoGetCurrentIrpStackLocation(Irp);
  3439. //
  3440. // Get the pointer to the input/output buffer and it's length
  3441. //
  3442. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  3443. outputBuffer = (PUSB_HCD_DRIVERKEY_NAME) Irp->AssociatedIrp.SystemBuffer;
  3444. Irp->IoStatus.Information = 0x0;
  3445. // find the PDO
  3446. if (outputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME)) {
  3447. // we have the PDO, now attempt to
  3448. // get the devnode name and return it
  3449. // the size of the buffer up to, but not including, the
  3450. // DriverKeyName field
  3451. adjustedDriverKeyNameSize =
  3452. sizeof(USB_HCD_DRIVERKEY_NAME) -
  3453. sizeof(outputBuffer->DriverKeyName);
  3454. length = outputBufferLength - adjustedDriverKeyNameSize;
  3455. ntStatus = IoGetDeviceProperty(
  3456. DeviceExtension->HcdPhysicalDeviceObject,
  3457. DevicePropertyDriverKeyName,
  3458. length,
  3459. outputBuffer->DriverKeyName,
  3460. &length);
  3461. outputBuffer->ActualLength =
  3462. length + adjustedDriverKeyNameSize;
  3463. if (NT_SUCCESS(ntStatus)) {
  3464. // fill in information field with the length actually copied
  3465. if (outputBuffer->ActualLength > outputBufferLength) {
  3466. // we just copied as much as we could
  3467. Irp->IoStatus.Information = outputBufferLength;
  3468. } else {
  3469. // user buffer contains the whole thing
  3470. Irp->IoStatus.Information = outputBuffer->ActualLength;
  3471. }
  3472. }
  3473. else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  3474. ntStatus = STATUS_SUCCESS;
  3475. outputBuffer->DriverKeyName[0] = L'\0';
  3476. Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME);
  3477. }
  3478. else {
  3479. // propagate the ntStatus value up
  3480. ;
  3481. }
  3482. } else {
  3483. ntStatus = STATUS_BUFFER_TOO_SMALL;
  3484. }
  3485. Irp->IoStatus.Status = ntStatus;
  3486. USBD_IoCompleteRequest (Irp,
  3487. IO_NO_INCREMENT);
  3488. }
  3489. break;
  3490. case IOCTL_USB_GET_ROOT_HUB_NAME:
  3491. *IrpNeedsCompletion = FALSE;
  3492. USBD_KdPrint(3, ("'IOCTL_USB_GET_ROOT_HUB_NAME\n"));
  3493. ntStatus =
  3494. Irp->IoStatus.Status = USBD_GetHubName(DeviceExtension, Irp);
  3495. USBD_IoCompleteRequest (Irp,
  3496. IO_NO_INCREMENT);
  3497. break;
  3498. default:
  3499. USBD_KdPrint(3, ("'USBD not handling ioctl\n"));
  3500. ntStatus = Irp->IoStatus.Status;
  3501. *IrpNeedsCompletion = TRUE;
  3502. } // switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  3503. break; // IRP_MJ_DEVICE_CONTROL
  3504. case IRP_MJ_SYSTEM_CONTROL:
  3505. *IrpNeedsCompletion = FALSE;
  3506. USBD_KdPrint(3, ("'IRP_MJ_SYSTEM_CONTROL\n"));
  3507. IoCopyCurrentIrpStackLocationToNext(Irp);
  3508. ntStatus = IoCallDriver(
  3509. DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3510. Irp);
  3511. break; // IRP_MJ_DEVICE_CONTROL
  3512. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  3513. switch(irpStack->Parameters.DeviceIoControl.IoControlCode) {
  3514. //
  3515. // This is where USBD pre-processes urbs passed to the
  3516. // host controller
  3517. //
  3518. case IOCTL_INTERNAL_USB_SUBMIT_URB:
  3519. USBD_KdPrint(3, ("'IOCTL_INTERNAL_USB_SUBMIT_URB\n"));
  3520. urb = irpStack->Parameters.Others.Argument1;
  3521. // The URB handler will mark the IRP pending if it
  3522. // has to pass it on, otherwise, we complete it here
  3523. // with the appropriate error
  3524. // a quick check of the function code will tell us if
  3525. // the urb if for HCD only
  3526. if ((urb->UrbHeader.Function & HCD_URB_FUNCTION) ||
  3527. (urb->UrbHeader.Function & HCD_NO_USBD_CALL)) {
  3528. // This is an HCD command, clear the renter bit
  3529. urb->UrbHeader.Function &= ~HCD_NO_USBD_CALL;
  3530. *IrpNeedsCompletion = TRUE;
  3531. } else {
  3532. ntStatus = USBD_ProcessURB(DeviceObject,
  3533. Irp,
  3534. urb,
  3535. IrpNeedsCompletion);
  3536. if (*IrpNeedsCompletion && NT_ERROR(ntStatus)) {
  3537. // the irp is marked pending
  3538. // but we have an error, reset
  3539. // the pending flag here so the HCD does
  3540. // not have to deal with this request
  3541. USBD_KdBreak(("Failing URB Request\n"));
  3542. *IrpNeedsCompletion = FALSE;
  3543. }
  3544. }
  3545. if (!*IrpNeedsCompletion) {
  3546. // USBD needs to complete the irp.
  3547. USBD_KdPrint(3, ("'USBD Completeing URB\n"));
  3548. Irp->IoStatus.Status = ntStatus;
  3549. USBD_IoCompleteRequest (Irp,
  3550. IO_NO_INCREMENT);
  3551. }
  3552. break;
  3553. case IOCTL_INTERNAL_USB_GET_BUSGUID_INFO:
  3554. {
  3555. // return the standard USB GUID
  3556. PPNP_BUS_INFORMATION busInfo;
  3557. *IrpNeedsCompletion = FALSE;
  3558. USBD_KdPrint(3, ("'IOCTL_INTERNAL_USB_GET_BUSGUID_INFO\n"));
  3559. busInfo = ExAllocatePoolWithTag(PagedPool,
  3560. sizeof(PNP_BUS_INFORMATION),
  3561. USBD_TAG);
  3562. if (busInfo == NULL) {
  3563. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3564. } else {
  3565. busInfo->BusTypeGuid = GUID_BUS_TYPE_USB;
  3566. busInfo->LegacyBusType = PNPBus;
  3567. busInfo->BusNumber = 0;
  3568. Irp->IoStatus.Information = (ULONG_PTR) busInfo;
  3569. ntStatus = STATUS_SUCCESS;
  3570. }
  3571. USBD_IoCompleteRequest (Irp,
  3572. IO_NO_INCREMENT);
  3573. }
  3574. break;
  3575. default:
  3576. USBD_KdPrint(3, ("'USBD not handling internal ioctl\n"));
  3577. ntStatus = Irp->IoStatus.Status;
  3578. *IrpNeedsCompletion = TRUE;
  3579. } // switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  3580. break; // IRP_MJ_INTERNAL_DEVICE_CONTROL
  3581. case IRP_MJ_PNP:
  3582. switch (irpStack->MinorFunction) {
  3583. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  3584. // pass on to host controllers PDO
  3585. *IrpNeedsCompletion = FALSE;
  3586. IoCopyCurrentIrpStackLocationToNext(Irp);
  3587. ntStatus =
  3588. IoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3589. Irp);
  3590. break;
  3591. case IRP_MN_QUERY_DEVICE_RELATIONS:
  3592. {
  3593. PDEVICE_OBJECT deviceObject;
  3594. USBD_KdPrint(1,
  3595. (" IRP_MN_QUERY_DEVICE_RELATIONS %x %x\n",
  3596. DeviceObject,
  3597. irpStack->Parameters.QueryDeviceRelations.Type));
  3598. ntStatus = STATUS_SUCCESS;
  3599. switch(irpStack->Parameters.QueryDeviceRelations.Type) {
  3600. case BusRelations:
  3601. // Don't use GETHEAP since OS will free and doesn't know about
  3602. // the trick GETHEAP does.
  3603. DeviceRelations=ExAllocatePoolWithTag(PagedPool,
  3604. sizeof(*DeviceRelations),
  3605. USBD_TAG);
  3606. if (!DeviceRelations) {
  3607. ntStatus=STATUS_INSUFFICIENT_RESOURCES;
  3608. break;
  3609. }
  3610. if (!DeviceExtension->RootHubPDO) {
  3611. PUSBD_EXTENSION pdoDeviceExtension;
  3612. ULONG index = 0;
  3613. UNICODE_STRING rootHubPdoUnicodeString;
  3614. do {
  3615. ntStatus =
  3616. USBD_InternalMakePdoName(&rootHubPdoUnicodeString,
  3617. index);
  3618. if (NT_SUCCESS(ntStatus)) {
  3619. ntStatus =
  3620. IoCreateDevice(DeviceExtension->DriverObject,
  3621. sizeof(PVOID),
  3622. &rootHubPdoUnicodeString,
  3623. FILE_DEVICE_BUS_EXTENDER,
  3624. 0,
  3625. FALSE,
  3626. &deviceObject);
  3627. if (!NT_SUCCESS(ntStatus)) {
  3628. RtlFreeUnicodeString(&rootHubPdoUnicodeString);
  3629. }
  3630. index++;
  3631. }
  3632. } while (ntStatus == STATUS_OBJECT_NAME_COLLISION);
  3633. //
  3634. // now create the root hub device and symbolic link
  3635. //
  3636. if (NT_SUCCESS(ntStatus)) {
  3637. deviceObject->Flags |= DO_POWER_PAGABLE;
  3638. pdoDeviceExtension = deviceObject->DeviceExtension;
  3639. DeviceExtension->RootHubPDO = deviceObject;
  3640. RtlFreeUnicodeString(&rootHubPdoUnicodeString);
  3641. USBD_KdPrint(3, ("'Create Root Hub stacksize = %d\n",
  3642. DeviceObject->StackSize));
  3643. deviceObject->StackSize = DeviceObject->StackSize;
  3644. pdoDeviceExtension->TrueDeviceExtension
  3645. = DeviceExtension;
  3646. pdoDeviceExtension->Flags = 0;
  3647. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  3648. ntStatus = STATUS_SUCCESS;
  3649. } else {
  3650. //
  3651. // failing to create the root hub
  3652. //
  3653. TEST_TRAP();
  3654. if (DeviceRelations) {
  3655. RETHEAP(DeviceRelations);
  3656. }
  3657. break;
  3658. }
  3659. }
  3660. //
  3661. // We support only one device (the root hub).
  3662. //
  3663. DeviceRelations->Count=1;
  3664. DeviceRelations->Objects[0]=DeviceExtension->RootHubPDO;
  3665. ObReferenceObject(DeviceExtension->RootHubPDO);
  3666. Irp->IoStatus.Information=(ULONG_PTR)DeviceRelations;
  3667. *IrpNeedsCompletion = FALSE;
  3668. Irp->IoStatus.Status = ntStatus;
  3669. USBD_KdPrint(1,
  3670. (" IRP_MN_QUERY_DEVICE_RELATIONS %x pass on %x\n",
  3671. DeviceObject,
  3672. irpStack->Parameters.QueryDeviceRelations.Type));
  3673. // pass it on
  3674. IoCopyCurrentIrpStackLocationToNext(Irp);
  3675. ntStatus =
  3676. IoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3677. Irp);
  3678. break;
  3679. case TargetDeviceRelation:
  3680. //
  3681. // this one gets passed on
  3682. //
  3683. USBD_KdPrint(1,
  3684. (" IRP_MN_QUERY_DEVICE_RELATIONS %x, TargetDeviceRelation\n",
  3685. DeviceObject));
  3686. // this PnP irp not handled by us
  3687. ntStatus = Irp->IoStatus.Status;
  3688. *IrpNeedsCompletion = TRUE;
  3689. break;
  3690. default:
  3691. //
  3692. // some other kind of relations
  3693. // pass this on
  3694. //
  3695. USBD_KdPrint(1,
  3696. (" IRP_MN_QUERY_DEVICE_RELATIONS %x, other relations\n",
  3697. DeviceObject));
  3698. *IrpNeedsCompletion = FALSE;
  3699. // pass it on
  3700. IoCopyCurrentIrpStackLocationToNext(Irp);
  3701. ntStatus =
  3702. IoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3703. Irp);
  3704. } /* case irpStack->Parameters.QueryDeviceRelations.Type */
  3705. }
  3706. break;
  3707. case IRP_MN_START_DEVICE:
  3708. {
  3709. USBD_KdPrint(3, ("'IRP_MN_START_DEVICE (fdo)\n"));
  3710. *IrpNeedsCompletion = FALSE;
  3711. KeInitializeEvent(&DeviceExtension->PnpStartEvent,
  3712. NotificationEvent,
  3713. FALSE);
  3714. USBD_KdPrint(3, ("'Set PnPIrp Completion Routine\n"));
  3715. IoCopyCurrentIrpStackLocationToNext(Irp);
  3716. IoSetCompletionRoutine(Irp,
  3717. USBD_PnPIrp_Complete,
  3718. // always pass FDO to completeion routine
  3719. DeviceExtension,
  3720. TRUE,
  3721. TRUE,
  3722. TRUE);
  3723. // pass on to host controllers PDO
  3724. ntStatus =
  3725. IoCallDriver(DeviceExtension->HcdTopOfPdoStackDeviceObject,
  3726. Irp);
  3727. if (ntStatus == STATUS_PENDING) {
  3728. KeWaitForSingleObject(
  3729. &DeviceExtension->PnpStartEvent,
  3730. Suspended,
  3731. KernelMode,
  3732. FALSE,
  3733. NULL);
  3734. ntStatus = Irp->IoStatus.Status;
  3735. }
  3736. if (NT_SUCCESS(ntStatus)) {
  3737. //
  3738. // irp completed by owner of PDO now start the HC
  3739. //
  3740. ntStatus =
  3741. DeviceExtension->HcdDeferredStartDevice(
  3742. DeviceExtension->HcdDeviceObject,
  3743. Irp);
  3744. // HC is now 'ON'
  3745. if (NT_SUCCESS(ntStatus)) {
  3746. DeviceExtension->HcCurrentDevicePowerState = PowerDeviceD0;
  3747. DeviceExtension->Flags |=USBDFLAG_HCD_STARTED;
  3748. }
  3749. }
  3750. #if DBG
  3751. else {
  3752. USBD_KdPrint(1,
  3753. (" Warning: Controller failed to start %x\n", ntStatus));
  3754. }
  3755. #endif
  3756. //
  3757. // we must complete this irp since we defrerred completion
  3758. // with the completion routine.
  3759. USBD_IoCompleteRequest(Irp,
  3760. IO_NO_INCREMENT);
  3761. }
  3762. break;
  3763. // Ken says take this out
  3764. // case IRP_MN_SURPRISE_REMOVAL:
  3765. // TEST_TRAP();
  3766. case IRP_MN_REMOVE_DEVICE:
  3767. USBD_KdPrint(3,
  3768. ("'IRP_MN_REMOVE_DEVICE (fdo), remove HCD sym link\n"));
  3769. if (DeviceExtension->DeviceLinkUnicodeString.Buffer) {
  3770. IoDeleteSymbolicLink(
  3771. &DeviceExtension->DeviceLinkUnicodeString);
  3772. RtlFreeUnicodeString(&DeviceExtension->DeviceLinkUnicodeString);
  3773. DeviceExtension->DeviceLinkUnicodeString.Buffer = NULL;
  3774. }
  3775. USBD_KdPrint(1,
  3776. ("'IRP_MN_REMOVE_DEVICE (fdo), remove root hub PDO\n"));
  3777. // note: we may not have a root hub PDO when we
  3778. // get created
  3779. if (DeviceExtension->RootHubPDO != NULL) {
  3780. USBD_KdPrint(1,
  3781. ("'Deleting root hub PDO now.\n"));
  3782. IoDeleteDevice(DeviceExtension->RootHubPDO);
  3783. }
  3784. DeviceExtension->RootHubPDO = NULL;
  3785. // Fall through
  3786. case IRP_MN_QUERY_CAPABILITIES:
  3787. case IRP_MN_QUERY_REMOVE_DEVICE:
  3788. case IRP_MN_CANCEL_REMOVE_DEVICE:
  3789. case IRP_MN_QUERY_STOP_DEVICE:
  3790. case IRP_MN_CANCEL_STOP_DEVICE:
  3791. //
  3792. // we do the default handling of the in USBD, that is
  3793. // return success.
  3794. // irpAssert expects these to be set to STATUS_SUCCESS
  3795. //
  3796. // note: these may also be handled by HC
  3797. // and HCD will pass the irp down to the PDO
  3798. //
  3799. ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  3800. *IrpNeedsCompletion = TRUE;
  3801. break;
  3802. case IRP_MN_STOP_DEVICE:
  3803. USBD_KdPrint(1,
  3804. ("'IRP_MN_STOP_DEVICE (fdo)\n"));
  3805. KeAcquireSpinLock(&DeviceExtension->WaitWakeSpin,
  3806. &irql);
  3807. // see if we need to cancel a wake irp
  3808. // in the HC
  3809. if (DeviceExtension->HcWakeIrp) {
  3810. PIRP hcwakeirp;
  3811. hcwakeirp = DeviceExtension->HcWakeIrp;
  3812. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  3813. irql);
  3814. USBD_KdPrint(1, ("USBD_FdoDispatch, MN_STOP: Canceling Wake Irp (%x) on HC PDO\n", hcwakeirp));
  3815. IoCancelIrp(hcwakeirp);
  3816. } else {
  3817. KeReleaseSpinLock(&DeviceExtension->WaitWakeSpin,
  3818. irql);
  3819. }
  3820. // note: HCD will pass the irp down to the PDO
  3821. ntStatus = Irp->IoStatus.Status;
  3822. *IrpNeedsCompletion = TRUE;
  3823. break;
  3824. default:
  3825. // PnP **
  3826. // message not handled, rule is that the
  3827. // status in the irp is not touched
  3828. //
  3829. // note: HCD will pass the irp down to the PDO
  3830. ntStatus = Irp->IoStatus.Status;
  3831. *IrpNeedsCompletion = TRUE;
  3832. } // switch (irpStack->MinorFunction)
  3833. break; // IRP_MJ_PNP
  3834. case IRP_MJ_POWER:
  3835. ntStatus = USBD_FdoPower(DeviceObject,
  3836. Irp,
  3837. DeviceExtension,
  3838. IrpNeedsCompletion);
  3839. break; // IRP_MJ_POWER
  3840. default:
  3841. //
  3842. // HCD irp not handled here
  3843. //
  3844. ntStatus = Irp->IoStatus.Status;
  3845. *IrpNeedsCompletion = TRUE;
  3846. } // switch (irpStack->MajorFunction)
  3847. return ntStatus;
  3848. }
  3849. VOID
  3850. USBD_CompleteRequest(
  3851. PIRP Irp,
  3852. CCHAR PriorityBoost
  3853. )
  3854. /*++
  3855. Routine Description:
  3856. Entry point called by HCD to complete an Irp.
  3857. Arguments:
  3858. Return Value:
  3859. NT status code.
  3860. --*/
  3861. {
  3862. PURB urb;
  3863. NTSTATUS ntStatus;
  3864. // USHORT function;
  3865. PHCD_URB hcdUrb;
  3866. PIO_STACK_LOCATION irpStack;
  3867. USBD_KdPrint(3, ("' enter USBD_CompleteRequest irp = %x\n", Irp));
  3868. irpStack = IoGetCurrentIrpStackLocation (Irp);
  3869. if (irpStack->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL) {
  3870. goto USBD_CompleteRequest_Done;
  3871. }
  3872. urb = URB_FROM_IRP(Irp);
  3873. hcdUrb = (PHCD_URB) urb;
  3874. //
  3875. // Free any resources we allocated to handle this URB
  3876. //
  3877. while (hcdUrb) {
  3878. if (hcdUrb->UrbHeader.UsbdFlags & USBD_REQUEST_MDL_ALLOCATED) {
  3879. USBD_ASSERT(hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL !=
  3880. NULL);
  3881. IoFreeMdl(hcdUrb->HcdUrbCommonTransfer.TransferBufferMDL);
  3882. }
  3883. if (hcdUrb->UrbHeader.UsbdFlags & USBD_REQUEST_IS_TRANSFER) {
  3884. hcdUrb = hcdUrb->HcdUrbCommonTransfer.UrbLink;
  3885. } else {
  3886. // only have linkage if this is a transfer.
  3887. break;
  3888. }
  3889. }
  3890. //
  3891. // If the irp completed with no error code but the URB has an
  3892. // error, map the error in the urb to an NT error code in the irp
  3893. // before the irp is completed.
  3894. //
  3895. // pass original status to USBD_MapError
  3896. ntStatus = Irp->IoStatus.Status;
  3897. // ntStatus now set to new 'mapped' error code
  3898. ntStatus = Irp->IoStatus.Status =
  3899. USBD_MapError_UrbToNT(urb, ntStatus);
  3900. USBD_KdPrint(3,
  3901. ("' exit USBD_CompleteRequest URB STATUS = (0x%x) NT STATUS = (0x%x)\n",
  3902. urb->UrbHeader.Status, ntStatus));
  3903. USBD_CompleteRequest_Done:
  3904. USBD_IoCompleteRequest (Irp,
  3905. PriorityBoost);
  3906. return;
  3907. }
  3908. #if 0
  3909. __declspec(dllexport)
  3910. PUSBD_INTETRFACE_INFORMATION
  3911. USBD_GetInterfaceInformation(
  3912. IN PURB Urb,
  3913. IN UCHAR InterfaceNumber
  3914. )
  3915. /*++
  3916. Routine Description:
  3917. Arguments:
  3918. Return Value:
  3919. --*/
  3920. {
  3921. PUSB_INTERFACE_INFORMATION foundInterface = NULL;
  3922. PUCHAR pch;
  3923. pch = &Urb->UrbSelectConfiguration.Interface;
  3924. while (pch - (PUCHAR)urb < Urb->SelectConfiguration.Length) {
  3925. interface = (PUSBD_INTERFACE_INFORMATION) pch;
  3926. if (interface->InterfaceNumber == InterfaceNumber) {
  3927. foundInterface = interface;
  3928. }
  3929. pch += interface->Length;
  3930. }
  3931. return foundInterface;
  3932. }
  3933. #endif
  3934. VOID
  3935. USBD_WaitDeviceMutex(
  3936. PDEVICE_OBJECT RootHubPDO
  3937. )
  3938. /*++
  3939. Routine Description:
  3940. Arguments:
  3941. Return Value:
  3942. interface descriptor or NULL.
  3943. --*/
  3944. {
  3945. PUSBD_EXTENSION deviceExtension;
  3946. PAGED_CODE();
  3947. deviceExtension = GET_DEVICE_EXTENSION(RootHubPDO);
  3948. USBD_WaitForUsbDeviceMutex(deviceExtension);
  3949. }
  3950. VOID
  3951. USBD_FreeDeviceMutex(
  3952. PDEVICE_OBJECT RootHubPDO
  3953. )
  3954. /*++
  3955. Routine Description:
  3956. Arguments:
  3957. Return Value:
  3958. interface descriptor or NULL.
  3959. --*/
  3960. {
  3961. PUSBD_EXTENSION deviceExtension;
  3962. PAGED_CODE();
  3963. deviceExtension = GET_DEVICE_EXTENSION(RootHubPDO);
  3964. USBD_ReleaseUsbDeviceMutex(deviceExtension);
  3965. }
  3966. //
  3967. // these apis are used to support the proprietary OEM
  3968. // no power suspend mode. (IBM APTIVA)
  3969. //
  3970. DEVICE_POWER_STATE
  3971. USBD_GetSuspendPowerState(
  3972. PDEVICE_OBJECT DeviceObject
  3973. )
  3974. /*++
  3975. Routine Description:
  3976. Arguments:
  3977. Return Value:
  3978. --*/
  3979. {
  3980. PUSBD_EXTENSION deviceExtension;
  3981. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  3982. return deviceExtension->SuspendPowerState;
  3983. }
  3984. VOID
  3985. USBD_SetSuspendPowerState(
  3986. PDEVICE_OBJECT DeviceObject,
  3987. DEVICE_POWER_STATE SuspendPowerState
  3988. )
  3989. /*++
  3990. Routine Description:
  3991. Arguments:
  3992. Return Value:
  3993. --*/
  3994. {
  3995. PUSBD_EXTENSION deviceExtension;
  3996. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  3997. deviceExtension->SuspendPowerState =
  3998. SuspendPowerState;
  3999. }
  4000. VOID
  4001. USBD_RegisterHcFilter(
  4002. PDEVICE_OBJECT DeviceObject,
  4003. PDEVICE_OBJECT FilterDeviceObject
  4004. )
  4005. /*++
  4006. Routine Description:
  4007. Arguments:
  4008. Return Value:
  4009. --*/
  4010. {
  4011. PUSBD_EXTENSION deviceExtension;
  4012. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  4013. deviceExtension->HcdTopOfStackDeviceObject = FilterDeviceObject;
  4014. }
  4015. VOID
  4016. USBD_RegisterHcDeviceCapabilities(
  4017. PDEVICE_OBJECT DeviceObject,
  4018. PDEVICE_CAPABILITIES DeviceCapabilities,
  4019. ROOT_HUB_POWER_FUNCTION *RootHubPower
  4020. )
  4021. /*++
  4022. Routine Description:
  4023. Arguments:
  4024. Return Value:
  4025. --*/
  4026. {
  4027. PUSBD_EXTENSION deviceExtension;
  4028. LONG i;
  4029. PDEVICE_CAPABILITIES rhDeviceCapabilities;
  4030. PDEVICE_CAPABILITIES hcDeviceCapabilities;
  4031. BOOLEAN bWakeSupported = FALSE;
  4032. deviceExtension = GET_DEVICE_EXTENSION(DeviceObject);
  4033. deviceExtension->RootHubPower = RootHubPower;
  4034. //
  4035. // HcDeviceCapabilities are set by the PDO below us and are unchanageable.
  4036. // RootHubDeviceCapabilities are howver set by us to describe the power
  4037. // properties of the root hub, and should therefore be set appropriately,
  4038. // but based on the power properities of our parent.
  4039. //
  4040. deviceExtension->RootHubDeviceCapabilities =
  4041. deviceExtension->HcDeviceCapabilities = *DeviceCapabilities;
  4042. rhDeviceCapabilities = &deviceExtension->RootHubDeviceCapabilities;
  4043. hcDeviceCapabilities = &deviceExtension->HcDeviceCapabilities;
  4044. //
  4045. // We can wake any device in on the USB bus so long as it is of D2 or better.
  4046. //
  4047. rhDeviceCapabilities->DeviceWake = PowerDeviceD2;
  4048. rhDeviceCapabilities->WakeFromD2 = TRUE;
  4049. rhDeviceCapabilities->WakeFromD1 = TRUE;
  4050. rhDeviceCapabilities->WakeFromD0 = TRUE;
  4051. rhDeviceCapabilities->DeviceD2 = TRUE;
  4052. rhDeviceCapabilities->DeviceD1 = TRUE;
  4053. //
  4054. // We cannot wake the system for any system sleeping state deeper than that
  4055. // of RootHubDeviceCapabilites->SystemWake, but if this value is
  4056. // unspecified, then we can set it to Working.
  4057. //
  4058. USBD_ASSERT(rhDeviceCapabilities->SystemWake >= PowerSystemUnspecified &&
  4059. rhDeviceCapabilities->SystemWake <= PowerSystemMaximum);
  4060. rhDeviceCapabilities->SystemWake =
  4061. (PowerSystemUnspecified == rhDeviceCapabilities->SystemWake) ?
  4062. PowerSystemWorking :
  4063. rhDeviceCapabilities->SystemWake;
  4064. rhDeviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
  4065. //
  4066. // For all values between PowerSystemSleeping1 and rhDeviceCaps->SystemWake
  4067. // we need to modify the power table.
  4068. //
  4069. // As long as we have power to the host controller we can give power to
  4070. // our children devices.
  4071. //
  4072. for (i=PowerSystemSleeping1; i < PowerSystemMaximum; i++) {
  4073. if (i > rhDeviceCapabilities->SystemWake) {
  4074. //
  4075. // For values above rhDeviceCaps->SystemWake, even our host controller
  4076. // should be set to D3.
  4077. //
  4078. if (PowerDeviceUnspecified == rhDeviceCapabilities->DeviceState[i]) {
  4079. rhDeviceCapabilities->DeviceState[i] = PowerDeviceD3;
  4080. }
  4081. // We know that for the host controller (or more correctly, the USB
  4082. // bus), D3 is not necessarily "OFF". If DeviceWake for the host
  4083. // controller is greater than or equal to D3, then we know that the
  4084. // USB bus has power at D3. Since most of the USB stack assumes
  4085. // that D3 == "OFF", we don't want to allow it to go to a lower
  4086. // power level than D2 if the USB bus will still have power at D3.
  4087. // We do this by setting the root hub's device state to D2 in this
  4088. // case.
  4089. if (rhDeviceCapabilities->DeviceState[i] == PowerDeviceD3 &&
  4090. rhDeviceCapabilities->DeviceState[i] <= hcDeviceCapabilities->DeviceWake) {
  4091. rhDeviceCapabilities->DeviceState[i] = PowerDeviceD2;
  4092. }
  4093. } else {
  4094. //
  4095. // We have some power so we can support low power on our bus
  4096. //
  4097. rhDeviceCapabilities->DeviceState[i] = PowerDeviceD2;
  4098. }
  4099. }
  4100. #if DBG
  4101. USBD_KdPrint(1, (" >>>>>> RH DeviceCaps\n"));
  4102. USBD_KdPrint(1, (" SystemWake = (%d)\n", rhDeviceCapabilities->SystemWake));
  4103. USBD_KdPrint(1, (" DeviceWake = (D%d)\n",
  4104. rhDeviceCapabilities->DeviceWake-1));
  4105. for (i=PowerSystemUnspecified; i< PowerSystemHibernate; i++) {
  4106. USBD_KdPrint(1, (" Device State Map: sysstate %d = devstate 0x%x\n", i,
  4107. rhDeviceCapabilities->DeviceState[i]));
  4108. }
  4109. USBD_KdBreak(("'>>>>>> RH DeviceCaps\n"));
  4110. USBD_KdPrint(1, (" >>>>>> HC DeviceCaps\n"));
  4111. USBD_KdPrint(1, (" SystemWake = (%d)\n", hcDeviceCapabilities->SystemWake));
  4112. USBD_KdPrint(1, (" DeviceWake = (D%d)\n",
  4113. hcDeviceCapabilities->DeviceWake-1));
  4114. for (i=PowerSystemUnspecified; i< PowerSystemHibernate; i++) {
  4115. USBD_KdPrint(1, ("'Device State Map: sysstate %d = devstate 0x%x\n", i,
  4116. hcDeviceCapabilities->DeviceState[i]));
  4117. }
  4118. USBD_KdBreak((" >>>>>> HC DeviceCaps\n"));
  4119. #endif
  4120. // Spit out message on the debugger indicating whether the HC and RH
  4121. // will support wake, according to the mapping tables.
  4122. USBD_KdPrint(1, (" \n\tWake support summary for HC:\n\n"));
  4123. if (hcDeviceCapabilities->SystemWake <= PowerSystemWorking) {
  4124. USBD_KdPrint(1, (" USB controller can't wake machine because SystemWake does not support it.\n"));
  4125. } else {
  4126. for (i = PowerSystemSleeping1, bWakeSupported = FALSE; i <= hcDeviceCapabilities->SystemWake; i++) {
  4127. if (hcDeviceCapabilities->DeviceState[i] != PowerDeviceUnspecified &&
  4128. hcDeviceCapabilities->DeviceState[i] <= hcDeviceCapabilities->DeviceWake) {
  4129. bWakeSupported = TRUE;
  4130. USBD_KdPrint(1, (" USB controller can wake machine from S%x (maps to D%x).\n",
  4131. i - 1, hcDeviceCapabilities->DeviceState[i] - 1));
  4132. }
  4133. }
  4134. if (!bWakeSupported) {
  4135. USBD_KdPrint(1, (" USB controller can't wake machine because DeviceState table does not support it.\n"));
  4136. }
  4137. }
  4138. deviceExtension->WakeSupported = bWakeSupported;
  4139. USBD_KdPrint(1, (" Low System Power states mapped to USB suspend\n"));
  4140. }
  4141. NTSTATUS
  4142. USBD_InternalMakePdoName(
  4143. IN OUT PUNICODE_STRING PdoNameUnicodeString,
  4144. IN ULONG Index
  4145. )
  4146. /*++
  4147. Routine Description:
  4148. This service Creates a name for a PDO created by the HUB
  4149. Arguments:
  4150. Return Value:
  4151. --*/
  4152. {
  4153. PWCHAR nameBuffer = NULL;
  4154. WCHAR rootName[] = L"\\Device\\USBPDO-";
  4155. UNICODE_STRING idUnicodeString;
  4156. WCHAR buffer[32];
  4157. NTSTATUS ntStatus = STATUS_SUCCESS;
  4158. USHORT length;
  4159. length = sizeof(buffer)+sizeof(rootName);
  4160. //
  4161. // use ExAllocate because client will free it
  4162. //
  4163. nameBuffer = ExAllocatePoolWithTag(PagedPool, length, USBD_TAG);
  4164. if (nameBuffer) {
  4165. RtlCopyMemory(nameBuffer, rootName, sizeof(rootName));
  4166. RtlInitUnicodeString(PdoNameUnicodeString,
  4167. nameBuffer);
  4168. PdoNameUnicodeString->MaximumLength =
  4169. length;
  4170. RtlInitUnicodeString(&idUnicodeString,
  4171. &buffer[0]);
  4172. idUnicodeString.MaximumLength =
  4173. sizeof(buffer);
  4174. ntStatus = RtlIntegerToUnicodeString(
  4175. Index,
  4176. 10,
  4177. &idUnicodeString);
  4178. if (NT_SUCCESS(ntStatus)) {
  4179. ntStatus = RtlAppendUnicodeStringToString(PdoNameUnicodeString,
  4180. &idUnicodeString);
  4181. }
  4182. USBD_KdPrint(3, ("'USBD_MakeNodeName string = %x\n",
  4183. PdoNameUnicodeString));
  4184. } else {
  4185. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  4186. }
  4187. if (!NT_SUCCESS(ntStatus) && nameBuffer) {
  4188. ExFreePool(nameBuffer);
  4189. }
  4190. return ntStatus;
  4191. }
  4192. NTSTATUS
  4193. USBD_MakePdoName(
  4194. IN OUT PUNICODE_STRING PdoNameUnicodeString,
  4195. IN ULONG Index
  4196. )
  4197. /*++
  4198. Routine Description:
  4199. Arguments:
  4200. Return Value:
  4201. --*/
  4202. {
  4203. return USBD_InternalMakePdoName(PdoNameUnicodeString, Index);
  4204. }
  4205. NTSTATUS
  4206. USBD_SymbolicLink(
  4207. BOOLEAN CreateFlag,
  4208. PUSBD_EXTENSION DeviceExtension
  4209. )
  4210. {
  4211. NTSTATUS ntStatus;
  4212. if (CreateFlag){
  4213. if (!DeviceExtension->RootHubPDO) {
  4214. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  4215. } else{
  4216. /*
  4217. * Create the symbolic link
  4218. */
  4219. ntStatus = IoRegisterDeviceInterface(
  4220. DeviceExtension->RootHubPDO,
  4221. (LPGUID)&GUID_CLASS_USBHUB,
  4222. NULL,
  4223. &DeviceExtension->RootHubSymbolicLinkName);
  4224. }
  4225. if (NT_SUCCESS(ntStatus)) {
  4226. /*
  4227. * Now set the symbolic link for the association and store it..
  4228. */
  4229. //ASSERT(ISPTR(pdoExt->name));
  4230. //
  4231. // (lonnym): Previously, the following call was being
  4232. // made with &DeviceExtension->RootHubPdoName passed as the
  4233. // second parameter.
  4234. // Code review this change, to see whether or not you still need
  4235. // to keep this information around.
  4236. //
  4237. // write the symbolic name to the registry
  4238. {
  4239. WCHAR hubNameKey[] = L"SymbolicName";
  4240. USBD_SetPdoRegistryParameter (
  4241. DeviceExtension->RootHubPDO,
  4242. &hubNameKey[0],
  4243. sizeof(hubNameKey),
  4244. &DeviceExtension->RootHubSymbolicLinkName.Buffer[0],
  4245. DeviceExtension->RootHubSymbolicLinkName.Length,
  4246. REG_SZ,
  4247. PLUGPLAY_REGKEY_DEVICE);
  4248. }
  4249. ntStatus =
  4250. IoSetDeviceInterfaceState(
  4251. &DeviceExtension->RootHubSymbolicLinkName, TRUE);
  4252. }
  4253. } else {
  4254. /*
  4255. * Disable the symbolic link
  4256. */
  4257. ntStatus = IoSetDeviceInterfaceState(
  4258. &DeviceExtension->RootHubSymbolicLinkName, FALSE);
  4259. ExFreePool(DeviceExtension->RootHubSymbolicLinkName.Buffer);
  4260. DeviceExtension->RootHubSymbolicLinkName.Buffer = NULL;
  4261. }
  4262. return ntStatus;
  4263. }
  4264. NTSTATUS
  4265. USBD_RestoreDeviceX(
  4266. IN OUT PUSBD_DEVICE_DATA OldDeviceData,
  4267. IN OUT PUSBD_DEVICE_DATA NewDeviceData,
  4268. IN PDEVICE_OBJECT DeviceObject
  4269. )
  4270. /*++
  4271. Routine Description:
  4272. Service exported for use by the hub driver
  4273. Our goal here is to re-create the device and restore the configuration.
  4274. Arguments:
  4275. Return Value:
  4276. NT status code.
  4277. --*/
  4278. {
  4279. NTSTATUS ntStatus = STATUS_SUCCESS;
  4280. PUSBD_CONFIG configHandle;
  4281. USBD_STATUS usbdStatus;
  4282. USBD_KdPrint(3, ("'enter USBD_RestoreDevice \n"));
  4283. if (OldDeviceData == NULL ||
  4284. NewDeviceData == NULL) {
  4285. return STATUS_INVALID_PARAMETER;
  4286. }
  4287. configHandle = OldDeviceData->ConfigurationHandle;
  4288. if (RtlCompareMemory(&NewDeviceData->DeviceDescriptor,
  4289. &OldDeviceData->DeviceDescriptor,
  4290. sizeof(OldDeviceData->DeviceDescriptor)) ==
  4291. sizeof(OldDeviceData->DeviceDescriptor)) {
  4292. NewDeviceData->ConfigurationHandle = configHandle;
  4293. //
  4294. // all the config and interface information is still valid,
  4295. // we just need to restore the pipe handles
  4296. //
  4297. ntStatus =
  4298. USBD_InternalRestoreConfiguration(
  4299. NewDeviceData,
  4300. DeviceObject,
  4301. NewDeviceData->ConfigurationHandle);
  4302. } else {
  4303. //
  4304. // free up the old config
  4305. //
  4306. ntStatus = USBD_InternalCloseConfiguration(OldDeviceData,
  4307. DeviceObject,
  4308. &usbdStatus,
  4309. TRUE,
  4310. FALSE);
  4311. ntStatus = STATUS_UNSUCCESSFUL;
  4312. }
  4313. //
  4314. // free the old data regardless
  4315. //
  4316. RETHEAP(OldDeviceData);
  4317. USBD_KdPrint(3, ("'exit USBD_ReCreateDevice 0x%x\n", ntStatus));
  4318. return ntStatus;
  4319. }
  4320. NTSTATUS
  4321. USBD_RestoreDevice(
  4322. IN OUT PUSBD_DEVICE_DATA OldDeviceData,
  4323. IN OUT PUSBD_DEVICE_DATA NewDeviceData,
  4324. IN PDEVICE_OBJECT DeviceObject
  4325. )
  4326. /*++
  4327. Routine Description:
  4328. Service exported for use by the hub driver
  4329. Our goal here is to re-create the device and restore the configuration.
  4330. Arguments:
  4331. Return Value:
  4332. NT status code.
  4333. --*/
  4334. {
  4335. USBD_KdPrint(0,
  4336. ("'WARNING: Driver using obsolete service enrty point (USBD_RestoreDevice) - get JD\n"));
  4337. return USBD_RestoreDeviceX(
  4338. OldDeviceData,
  4339. NewDeviceData,
  4340. DeviceObject);
  4341. }
  4342. NTSTATUS
  4343. USBD_SetPdoRegistryParameter (
  4344. IN PDEVICE_OBJECT PhysicalDeviceObject,
  4345. IN PWCHAR KeyName,
  4346. IN ULONG KeyNameLength,
  4347. IN PVOID Data,
  4348. IN ULONG DataLength,
  4349. IN ULONG KeyType,
  4350. IN ULONG DevInstKeyType
  4351. )
  4352. /*++
  4353. Routine Description:
  4354. Arguments:
  4355. Return Value:
  4356. --*/
  4357. {
  4358. NTSTATUS ntStatus;
  4359. HANDLE handle;
  4360. UNICODE_STRING keyNameUnicodeString;
  4361. PAGED_CODE();
  4362. RtlInitUnicodeString(&keyNameUnicodeString, KeyName);
  4363. ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  4364. DevInstKeyType,
  4365. STANDARD_RIGHTS_ALL,
  4366. &handle);
  4367. if (NT_SUCCESS(ntStatus)) {
  4368. /*
  4369. RtlInitUnicodeString(&keyName, L"DeviceFoo");
  4370. ZwSetValueKey(handle,
  4371. &keyName,
  4372. 0,
  4373. REG_DWORD,
  4374. ComplienceFlags,
  4375. sizeof(*ComplienceFlags));
  4376. */
  4377. USBD_SetRegistryKeyValue(handle,
  4378. &keyNameUnicodeString,
  4379. Data,
  4380. DataLength,
  4381. KeyType);
  4382. ZwClose(handle);
  4383. }
  4384. USBD_KdPrint(3, ("' RtlQueryRegistryValues status 0x%x\n"));
  4385. return ntStatus;
  4386. }
  4387. NTSTATUS
  4388. USBD_SetRegistryKeyValue (
  4389. IN HANDLE Handle,
  4390. IN PUNICODE_STRING KeyNameUnicodeString,
  4391. IN PVOID Data,
  4392. IN ULONG DataLength,
  4393. IN ULONG KeyType
  4394. )
  4395. /*++
  4396. Routine Description:
  4397. Arguments:
  4398. Return Value:
  4399. --*/
  4400. {
  4401. NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  4402. PAGED_CODE();
  4403. // InitializeObjectAttributes( &objectAttributes,
  4404. // KeyNameString,
  4405. // OBJ_CASE_INSENSITIVE,
  4406. // Handle,
  4407. // (PSECURITY_DESCRIPTOR) NULL );
  4408. //
  4409. // Create the key or open it, as appropriate based on the caller's
  4410. // wishes.
  4411. //
  4412. #if 0
  4413. ntStatus = ZwCreateKey( Handle,
  4414. DesiredAccess,
  4415. &objectAttributes,
  4416. 0,
  4417. (PUNICODE_STRING) NULL,
  4418. REG_OPTION_VOLATILE,
  4419. &disposition );
  4420. #endif
  4421. ntStatus = ZwSetValueKey(Handle,
  4422. KeyNameUnicodeString,
  4423. 0,
  4424. KeyType,
  4425. Data,
  4426. DataLength);
  4427. USBD_KdPrint(3, ("' ZwSetKeyValue = 0x%x\n", ntStatus));
  4428. return ntStatus;
  4429. }
  4430. NTSTATUS
  4431. USBD_QueryBusTime(
  4432. IN PDEVICE_OBJECT RootHubPdo,
  4433. IN PULONG CurrentFrame
  4434. )
  4435. /*++
  4436. Routine Description:
  4437. get the HCD current frame, callable at any IRQL
  4438. Arguments:
  4439. Return Value:
  4440. --*/
  4441. {
  4442. PUSBD_EXTENSION deviceExtension;
  4443. USBD_KdPrint(0,
  4444. ("'WARNING: Driver using obsolete service enrty point (USBD_QueryBusTime) - get JD\n"));
  4445. deviceExtension = RootHubPdo->DeviceExtension;
  4446. deviceExtension = deviceExtension->TrueDeviceExtension;
  4447. return deviceExtension->HcdGetCurrentFrame(
  4448. deviceExtension->HcdDeviceObject,
  4449. CurrentFrame);
  4450. }
  4451. #else // USBD_DRIVER
  4452. // Obsolete functions that are still exported are stubbed out here.
  4453. ULONG
  4454. USBD_AllocateDeviceName(
  4455. PUNICODE_STRING DeviceNameUnicodeString
  4456. )
  4457. {
  4458. ULONG i = 0;
  4459. PAGED_CODE();
  4460. ASSERT(FALSE);
  4461. return i;
  4462. }
  4463. VOID
  4464. USBD_CompleteRequest(
  4465. PIRP Irp,
  4466. CCHAR PriorityBoost
  4467. )
  4468. {
  4469. ASSERT(FALSE);
  4470. return;
  4471. }
  4472. NTSTATUS
  4473. USBD_CreateDevice(
  4474. IN OUT PUSBD_DEVICE_DATA *DeviceData,
  4475. IN PDEVICE_OBJECT DeviceObject,
  4476. IN BOOLEAN DeviceIsLowSpeed,
  4477. IN ULONG MaxPacketSize_Endpoint0,
  4478. IN OUT PULONG DeviceHackFlags
  4479. )
  4480. {
  4481. USBD_KdPrint(0,
  4482. ("'WARNING: Driver using obsolete service entry point (USBD_CreateDevice) - get JD\n"));
  4483. ASSERT(FALSE);
  4484. return STATUS_NOT_SUPPORTED;
  4485. }
  4486. BOOLEAN
  4487. USBD_Dispatch(
  4488. PDEVICE_OBJECT DeviceObject,
  4489. PIRP Irp,
  4490. PDEVICE_OBJECT *HcdDeviceObject,
  4491. NTSTATUS *NtStatus
  4492. )
  4493. {
  4494. BOOLEAN irpNeedsCompletion = TRUE;
  4495. ASSERT(FALSE);
  4496. return irpNeedsCompletion;
  4497. }
  4498. VOID
  4499. USBD_FreeDeviceMutex(
  4500. PDEVICE_OBJECT RootHubPDO
  4501. )
  4502. {
  4503. PAGED_CODE();
  4504. ASSERT(FALSE);
  4505. return;
  4506. }
  4507. VOID
  4508. USBD_FreeDeviceName(
  4509. ULONG DeviceNameHandle
  4510. )
  4511. {
  4512. PAGED_CODE();
  4513. ASSERT(FALSE);
  4514. return;
  4515. }
  4516. NTSTATUS
  4517. USBD_GetDeviceInformation(
  4518. IN PUSB_NODE_CONNECTION_INFORMATION DeviceInformation,
  4519. IN ULONG DeviceInformationLength,
  4520. IN PUSBD_DEVICE_DATA DeviceData
  4521. )
  4522. {
  4523. USBD_KdPrint(0,
  4524. (" WARNING: Driver using obsolete service enrty point (USBD_GetDeviceInformation) - get JD\n"));
  4525. ASSERT(FALSE);
  4526. return STATUS_NOT_SUPPORTED;
  4527. }
  4528. DEVICE_POWER_STATE
  4529. USBD_GetSuspendPowerState(
  4530. PDEVICE_OBJECT DeviceObject
  4531. )
  4532. {
  4533. ASSERT(FALSE);
  4534. return 0;
  4535. }
  4536. NTSTATUS
  4537. USBD_InitializeDevice(
  4538. IN PUSBD_DEVICE_DATA DeviceData,
  4539. IN PDEVICE_OBJECT DeviceObject,
  4540. IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
  4541. IN ULONG DeviceDescriptorLength,
  4542. IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
  4543. IN ULONG ConfigDescriptorLength
  4544. )
  4545. {
  4546. USBD_KdPrint(0,
  4547. ("'WARNING: Driver using obsolete service enrty point (USBD_InitializeDevice) - get JD\n"));
  4548. ASSERT(FALSE);
  4549. return STATUS_NOT_SUPPORTED;
  4550. }
  4551. NTSTATUS
  4552. USBD_MakePdoName(
  4553. IN OUT PUNICODE_STRING PdoNameUnicodeString,
  4554. IN ULONG Index
  4555. )
  4556. {
  4557. ASSERT(FALSE);
  4558. return STATUS_NOT_SUPPORTED;
  4559. }
  4560. NTSTATUS
  4561. USBD_QueryBusTime(
  4562. IN PDEVICE_OBJECT RootHubPdo,
  4563. IN PULONG CurrentFrame
  4564. )
  4565. {
  4566. USBD_KdPrint(0,
  4567. ("'WARNING: Driver using obsolete service enrty point (USBD_QueryBusTime) - get JD\n"));
  4568. ASSERT(FALSE);
  4569. return STATUS_NOT_SUPPORTED;
  4570. }
  4571. VOID
  4572. USBD_RegisterHcDeviceCapabilities(
  4573. PDEVICE_OBJECT DeviceObject,
  4574. PDEVICE_CAPABILITIES DeviceCapabilities,
  4575. ROOT_HUB_POWER_FUNCTION *RootHubPower
  4576. )
  4577. {
  4578. ASSERT(FALSE);
  4579. return;
  4580. }
  4581. VOID
  4582. USBD_RegisterHcFilter(
  4583. PDEVICE_OBJECT DeviceObject,
  4584. PDEVICE_OBJECT FilterDeviceObject
  4585. )
  4586. {
  4587. ASSERT(FALSE);
  4588. }
  4589. NTSTATUS
  4590. USBD_RegisterHostController(
  4591. IN PDEVICE_OBJECT PhysicalDeviceObject,
  4592. IN PDEVICE_OBJECT HcdDeviceObject,
  4593. IN PDEVICE_OBJECT HcdTopOfPdoStackDeviceObject,
  4594. IN PDRIVER_OBJECT HcdDriverObject,
  4595. IN HCD_DEFFERED_START_FUNCTION *HcdDeferredStartDevice,
  4596. IN HCD_SET_DEVICE_POWER_STATE *HcdSetDevicePowerState,
  4597. IN HCD_GET_CURRENT_FRAME *HcdGetCurrentFrame,
  4598. IN HCD_GET_CONSUMED_BW *HcdGetConsumedBW,
  4599. IN HCD_SUBMIT_ISO_URB *HcdSubmitIsoUrb,
  4600. // this parameter is only needed until we resolve device naming
  4601. // issues with PNP
  4602. IN ULONG HcdDeviceNameHandle
  4603. )
  4604. {
  4605. PAGED_CODE();
  4606. ASSERT(FALSE);
  4607. return STATUS_NOT_SUPPORTED;
  4608. }
  4609. NTSTATUS
  4610. USBD_RemoveDevice(
  4611. IN PUSBD_DEVICE_DATA DeviceData,
  4612. IN PDEVICE_OBJECT DeviceObject,
  4613. IN UCHAR Flags
  4614. )
  4615. {
  4616. USBD_KdPrint(0,
  4617. ("'WARNING: Driver using obsolete service enrty point (USBD_RemoveDevice) - get JD\n"));
  4618. ASSERT(FALSE);
  4619. return STATUS_NOT_SUPPORTED;
  4620. }
  4621. NTSTATUS
  4622. USBD_RestoreDevice(
  4623. IN OUT PUSBD_DEVICE_DATA OldDeviceData,
  4624. IN OUT PUSBD_DEVICE_DATA NewDeviceData,
  4625. IN PDEVICE_OBJECT DeviceObject
  4626. )
  4627. {
  4628. USBD_KdPrint(0,
  4629. ("'WARNING: Driver using obsolete service enrty point (USBD_RestoreDevice) - get JD\n"));
  4630. ASSERT(FALSE);
  4631. return STATUS_NOT_SUPPORTED;
  4632. }
  4633. VOID
  4634. USBD_SetSuspendPowerState(
  4635. PDEVICE_OBJECT DeviceObject,
  4636. DEVICE_POWER_STATE SuspendPowerState
  4637. )
  4638. {
  4639. ASSERT(FALSE);
  4640. return;
  4641. }
  4642. VOID
  4643. USBD_WaitDeviceMutex(
  4644. PDEVICE_OBJECT RootHubPDO
  4645. )
  4646. {
  4647. ASSERT(FALSE);
  4648. return;
  4649. }
  4650. #endif // USBD_DRIVER