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.

3055 lines
90 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. IOCTLI.C
  5. Abstract:
  6. This module implements usb IOCTL requests to usb hub.
  7. Author:
  8. jdunn
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. 1-2-97 : re-wriiten
  14. --*/
  15. /*
  16. //
  17. // ** User mode IOCTLS **
  18. //
  19. //
  20. // IOCTL_USB_GET_NODE_INFORMATION
  21. //
  22. input:
  23. None
  24. output:
  25. outputbufferlength = sizeof(USB_BUS_NODE_INFORMATION)
  26. outputbuffer = filled in with USB_BUS_NODE_INFORMATION structure.
  27. //
  28. // IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
  29. //
  30. input:
  31. inputbufferlength = size of user supplied buffer
  32. inpubuffer = ptr to USB_NODE_CONNECTION_INFORMATION structure with
  33. connectionIndex set to the requested connection.
  34. output:
  35. outputbufferlength = size of user supplied buffer
  36. outputbuffer = filled in with USB_NODE_CONNECTION_INFORMATION structure.
  37. //
  38. // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
  39. //
  40. input:
  41. inputbufferlength = size of user supplied buffer.
  42. inputbuffer = ptr to USB_DESCRIPTOR_REQUEST, includes setup packet
  43. and connection index.
  44. output:
  45. outputbufferlength = length of descriptor data plus sizeof sizeof(USB_DESCRIPTOR_REQUEST).
  46. outputbuffer = ptr to USB_DESCRIPTOR_REQUEST filled in with returned data.
  47. //
  48. // ** Internal IOCTLS **
  49. //
  50. //
  51. // IOCTL_INTERNAL_USB_RESET_PORT
  52. //
  53. */
  54. #include <wdm.h>
  55. #ifdef WMI_SUPPORT
  56. #include <wmilib.h>
  57. #include <wmistr.h>
  58. #include <wdmguid.h>
  59. #endif /* WMI_SUPPORT */
  60. #include "usbhub.h"
  61. #ifdef PAGE_CODE
  62. #ifdef ALLOC_PRAGMA
  63. #pragma alloc_text(PAGE, USBH_IoctlGetNodeInformation)
  64. #pragma alloc_text(PAGE, USBH_IoctlGetHubCapabilities)
  65. #pragma alloc_text(PAGE, USBH_IoctlGetNodeConnectionInformation)
  66. #pragma alloc_text(PAGE, USBH_IoctlGetNodeConnectionDriverKeyName)
  67. #pragma alloc_text(PAGE, USBH_IoctlGetNodeName)
  68. #pragma alloc_text(PAGE, USBH_PdoIoctlGetPortStatus)
  69. #pragma alloc_text(PAGE, USBH_PdoIoctlEnablePort)
  70. #pragma alloc_text(PAGE, USBH_IoctlGetDescriptorForPDO)
  71. #pragma alloc_text(PAGE, USBH_SystemControl)
  72. #pragma alloc_text(PAGE, USBH_PortSystemControl)
  73. #pragma alloc_text(PAGE, USBH_ExecuteWmiMethod)
  74. #pragma alloc_text(PAGE, USBH_QueryWmiRegInfo)
  75. #pragma alloc_text(PAGE, USBH_CheckLeafHubsIdle)
  76. #endif
  77. #endif
  78. NTSTATUS
  79. USBH_IoctlGetNodeInformation(
  80. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  81. IN PIRP Irp
  82. )
  83. /* ++
  84. *
  85. * Description:
  86. *
  87. * Arguments:
  88. *
  89. * Return:
  90. *
  91. * NTSTATUS
  92. *
  93. * -- */
  94. {
  95. NTSTATUS ntStatus = STATUS_SUCCESS;
  96. PIO_STACK_LOCATION ioStack;
  97. PUSB_NODE_INFORMATION outputBuffer;
  98. ULONG outputBufferLength;
  99. PAGED_CODE();
  100. USBH_KdPrint((2,"'USBH_IoctlGetNodeInformation\n"));
  101. //
  102. // Get a pointer to the current location in the Irp. This is where
  103. // the function codes and parameters are located.
  104. //
  105. ioStack = IoGetCurrentIrpStackLocation(Irp);
  106. //
  107. // Get the pointer to the input/output buffer and it's length
  108. //
  109. outputBuffer = (PUSB_NODE_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
  110. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  111. RtlZeroMemory(outputBuffer, outputBufferLength);
  112. if (outputBufferLength >= sizeof(USB_NODE_INFORMATION)) {
  113. //
  114. // for now everything is a hub
  115. //
  116. outputBuffer->NodeType = UsbHub;
  117. RtlCopyMemory(&outputBuffer->u.HubInformation.HubDescriptor,
  118. DeviceExtensionHub->HubDescriptor,
  119. sizeof(outputBuffer->u.HubInformation));
  120. // 100 milliamps/port means bus powered
  121. outputBuffer->u.HubInformation.HubIsBusPowered =
  122. USBH_HubIsBusPowered(DeviceExtensionHub->FunctionalDeviceObject,
  123. DeviceExtensionHub->ConfigurationDescriptor);
  124. Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
  125. } else {
  126. ntStatus = STATUS_BUFFER_TOO_SMALL;
  127. }
  128. USBH_CompleteIrp(Irp, ntStatus);
  129. return ntStatus;
  130. }
  131. NTSTATUS
  132. USBH_IoctlCycleHubPort(
  133. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  134. IN PIRP Irp
  135. )
  136. /* ++
  137. *
  138. * Description:
  139. *
  140. * Arguments:
  141. *
  142. * Return:
  143. *
  144. * NTSTATUS
  145. *
  146. * -- */
  147. {
  148. NTSTATUS ntStatus = STATUS_SUCCESS;
  149. PIO_STACK_LOCATION ioStack;
  150. PULONG buffer;
  151. ULONG bufferLength;
  152. ULONG port;
  153. PAGED_CODE();
  154. USBH_KdPrint((2,"'USBH_IoctlCycleHubPort\n"));
  155. ioStack = IoGetCurrentIrpStackLocation(Irp);
  156. //
  157. // Get the pointer to the input/output buffer and its length.
  158. //
  159. buffer = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  160. bufferLength = ioStack->Parameters.DeviceIoControl.InputBufferLength;
  161. if (bufferLength < sizeof(port)) {
  162. ntStatus = STATUS_BUFFER_TOO_SMALL;
  163. goto USBH_IoctlCycleHubPort_Done;
  164. }
  165. // port number is input only
  166. port = *buffer;
  167. Irp->IoStatus.Information = 0;
  168. USBH_KdPrint((1,"'Request Cycle Port %d\n", port));
  169. if (port <= DeviceExtensionHub->HubDescriptor->bNumberOfPorts &&
  170. port > 0) {
  171. PPORT_DATA portData;
  172. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  173. portData = &DeviceExtensionHub->PortData[port-1];
  174. if (portData->DeviceObject) {
  175. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  176. USBH_InternalCyclePort(DeviceExtensionHub,
  177. (USHORT) port,
  178. deviceExtensionPort);
  179. } else {
  180. ntStatus = STATUS_UNSUCCESSFUL;
  181. }
  182. USBH_KdPrint((1,"'Cycle Port %d %x\n", port, ntStatus));
  183. }
  184. USBH_IoctlCycleHubPort_Done:
  185. USBH_CompleteIrp(Irp, ntStatus);
  186. return ntStatus;
  187. }
  188. NTSTATUS
  189. USBH_IoctlGetHubCapabilities(
  190. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  191. IN PIRP Irp
  192. )
  193. /* ++
  194. *
  195. * Description:
  196. *
  197. * Arguments:
  198. *
  199. * Return:
  200. *
  201. * NTSTATUS
  202. *
  203. * -- */
  204. {
  205. NTSTATUS ntStatus = STATUS_SUCCESS;
  206. PIO_STACK_LOCATION ioStack;
  207. PUSB_HUB_CAPABILITIES outputBuffer;
  208. ULONG outputBufferLength, copyLen;
  209. USB_HUB_CAPABILITIES localBuffer;
  210. PAGED_CODE();
  211. USBH_KdPrint((2,"'USBH_IoctlGetHubCapabilities\n"));
  212. RtlZeroMemory(&localBuffer, sizeof(USB_HUB_CAPABILITIES));
  213. // Fill in the data in the local buffer first, then copy as much of
  214. // this data to the user's buffer as requested (as indicated by the
  215. // size of the request buffer).
  216. localBuffer.HubIs2xCapable =
  217. (DeviceExtensionHub->HubFlags & HUBFLAG_USB20_HUB) ? 1:0;
  218. //
  219. // Get a pointer to the current location in the Irp. This is where
  220. // the function codes and parameters are located.
  221. //
  222. ioStack = IoGetCurrentIrpStackLocation(Irp);
  223. //
  224. // Get the pointer to the input/output buffer and its length.
  225. //
  226. outputBuffer = (PUSB_HUB_CAPABILITIES) Irp->AssociatedIrp.SystemBuffer;
  227. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  228. if (outputBufferLength <= sizeof(localBuffer)) {
  229. copyLen = outputBufferLength;
  230. } else {
  231. copyLen = sizeof(localBuffer);
  232. }
  233. // zero buffer passed in
  234. RtlZeroMemory(outputBuffer,
  235. outputBufferLength);
  236. // Only give the user the amount of data that they ask for
  237. // this may only be part of our info strucure
  238. RtlCopyMemory(outputBuffer,
  239. &localBuffer,
  240. copyLen);
  241. Irp->IoStatus.Information = copyLen;
  242. USBH_CompleteIrp(Irp, ntStatus);
  243. return ntStatus;
  244. }
  245. NTSTATUS
  246. USBH_IoctlGetNodeConnectionDriverKeyName(
  247. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  248. IN PIRP Irp
  249. )
  250. /* ++
  251. *
  252. * Description:
  253. *
  254. * Arguments:
  255. *
  256. * ConnectionIndex - The one-based port index to which a device is attached.
  257. * The devnode name of the will be returned, if there is sufficient buffer space.
  258. *
  259. * ActualLength - The structure size in bytes necessary to hold the NULL
  260. * terminated name. This includes the entire structure, not
  261. * just the name.
  262. *
  263. * NodeName - The UNICODE NULL terminated name of the devnode for the device
  264. * attached to this port.
  265. *
  266. * Return:
  267. *
  268. * NTSTATUS
  269. *
  270. * -- */
  271. {
  272. NTSTATUS ntStatus = STATUS_SUCCESS;
  273. PIO_STACK_LOCATION ioStack;
  274. PUSB_NODE_CONNECTION_DRIVERKEY_NAME outputBuffer;
  275. ULONG outputBufferLength, length, i;
  276. PPORT_DATA portData;
  277. PAGED_CODE();
  278. USBH_KdPrint((2,"'USBH_IoctlGetNodeConnectionDriverKeyName\n"));
  279. portData = DeviceExtensionHub->PortData;
  280. //
  281. // Get a pointer to the current location in the Irp. This is where
  282. // the function codes and parameters are located.
  283. //
  284. ioStack = IoGetCurrentIrpStackLocation(Irp);
  285. //
  286. // Get the pointer to the input/output buffer and it's length
  287. //
  288. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  289. outputBuffer = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME) Irp->AssociatedIrp.SystemBuffer;
  290. // find the PDO
  291. if (outputBufferLength >= sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME)) {
  292. USBH_KdPrint((2,"'Connection = %d\n", outputBuffer->ConnectionIndex));
  293. ntStatus = STATUS_INVALID_PARAMETER;
  294. for(i=1; i<=DeviceExtensionHub->HubDescriptor->bNumberOfPorts; i++) {
  295. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  296. if (i == outputBuffer->ConnectionIndex) {
  297. portData = &DeviceExtensionHub->PortData[outputBuffer->ConnectionIndex - 1];
  298. if (portData->DeviceObject) {
  299. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  300. // Validate the PDO for PnP purposes. (PnP will bugcheck
  301. // if passed a not-quite-initialized PDO.)
  302. if (deviceExtensionPort->PortPdoFlags &
  303. PORTPDO_VALID_FOR_PNP_FUNCTION) {
  304. // we have the PDO, now attempt to
  305. // get the devnode name and return it
  306. length = outputBufferLength -
  307. sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
  308. ntStatus = IoGetDeviceProperty(
  309. portData->DeviceObject,
  310. DevicePropertyDriverKeyName,
  311. length,
  312. outputBuffer->DriverKeyName,
  313. &length);
  314. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  315. ntStatus = STATUS_SUCCESS;
  316. }
  317. outputBuffer->ActualLength =
  318. length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
  319. // see how much data we actully copied
  320. if (outputBufferLength > outputBuffer->ActualLength) {
  321. // user buffer is bigger, just indicate how much we copied
  322. Irp->IoStatus.Information = outputBuffer->ActualLength;
  323. } else {
  324. // we copied as much as would fit
  325. Irp->IoStatus.Information = outputBufferLength;
  326. }
  327. } else {
  328. ntStatus = STATUS_INVALID_DEVICE_STATE;
  329. }
  330. }
  331. }
  332. }
  333. } else {
  334. ntStatus = STATUS_BUFFER_TOO_SMALL;
  335. }
  336. USBH_CompleteIrp(Irp, ntStatus);
  337. return ntStatus;
  338. }
  339. NTSTATUS
  340. USBH_IoctlGetNodeConnectionInformation(
  341. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  342. IN PIRP Irp,
  343. IN BOOLEAN ExApi
  344. )
  345. /* ++
  346. *
  347. * Description:
  348. *
  349. * Arguments:
  350. *
  351. * Return:
  352. *
  353. * NTSTATUS
  354. *
  355. * -- */
  356. {
  357. NTSTATUS ntStatus = STATUS_SUCCESS;
  358. PIO_STACK_LOCATION ioStack;
  359. PUSB_NODE_CONNECTION_INFORMATION_EX outputBuffer;
  360. ULONG outputBufferLength, length, i;
  361. PPORT_DATA portData;
  362. PAGED_CODE();
  363. USBH_KdPrint((2,"'USBH_IoctlGetNodeConnectionInformation\n"));
  364. portData = DeviceExtensionHub->PortData;
  365. //
  366. // Get a pointer to the current location in the Irp. This is where
  367. // the function codes and parameters are located.
  368. //
  369. ioStack = IoGetCurrentIrpStackLocation(Irp);
  370. //
  371. // Get the pointer to the input/output buffer and it's length
  372. //
  373. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  374. outputBuffer = (PUSB_NODE_CONNECTION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
  375. if (outputBufferLength >= sizeof(USB_NODE_CONNECTION_INFORMATION)) {
  376. ULONG index;
  377. USBH_KdPrint((2,"'Connection = %d\n", outputBuffer->ConnectionIndex));
  378. // Clear the buffer in case we don't call USBD_GetDeviceInformation
  379. // below, but make sure to keep the ConnectionIndex!
  380. index = outputBuffer->ConnectionIndex;
  381. RtlZeroMemory(outputBuffer, outputBufferLength);
  382. outputBuffer->ConnectionIndex = index;
  383. ntStatus = STATUS_INVALID_PARAMETER;
  384. for(i=1; i<=DeviceExtensionHub->HubDescriptor->bNumberOfPorts; i++) {
  385. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  386. if (i == outputBuffer->ConnectionIndex) {
  387. length = sizeof(USB_NODE_CONNECTION_INFORMATION);
  388. if (portData->DeviceObject) {
  389. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  390. outputBuffer->ConnectionStatus =
  391. portData->ConnectionStatus;
  392. outputBuffer->DeviceIsHub =
  393. (deviceExtensionPort->PortPdoFlags & PORTPDO_DEVICE_IS_HUB)
  394. ? TRUE : FALSE;
  395. USBH_KdPrint((2,"'outputbuffer = %x\n", outputBuffer));
  396. RtlCopyMemory(&outputBuffer->DeviceDescriptor,
  397. &deviceExtensionPort->DeviceDescriptor,
  398. sizeof(outputBuffer->DeviceDescriptor));
  399. if (deviceExtensionPort->DeviceData) {
  400. #ifdef USB2
  401. USBH_KdPrint((2,"'devicedata = %x\n",
  402. deviceExtensionPort->DeviceData));
  403. ntStatus = USBD_GetDeviceInformationEx(
  404. deviceExtensionPort,
  405. DeviceExtensionHub,
  406. outputBuffer,
  407. outputBufferLength,
  408. deviceExtensionPort->DeviceData);
  409. #else
  410. ntStatus = USBD_GetDeviceInformation(outputBuffer,
  411. outputBufferLength,
  412. deviceExtensionPort->DeviceData);
  413. #endif
  414. } else {
  415. //
  416. // We have a device connected, but it failed to start.
  417. // Since it hasn't started, there are no open pipes, so
  418. // we don't need to get pipe information. We are going
  419. // to return some relevant information, however, so
  420. // return STATUS_SUCCESS.
  421. //
  422. ntStatus = STATUS_SUCCESS;
  423. }
  424. USBH_KdPrint((2,"'status from USBD_GetDeviceInformation %x\n",
  425. ntStatus));
  426. if (NT_SUCCESS(ntStatus)) {
  427. ULONG j;
  428. USBH_KdPrint((2,"'status %x \n", outputBuffer->ConnectionStatus));
  429. // USBH_KdPrint((2,"'NodeName %s\n", outputBuffer->NodeName));
  430. USBH_KdPrint((2,"'PID 0x%x\n",
  431. outputBuffer->DeviceDescriptor.idProduct));
  432. USBH_KdPrint((2,"'VID 0x%x\n",
  433. outputBuffer->DeviceDescriptor.idVendor));
  434. USBH_KdPrint((2,"'Current Configuration Value 0x%x\n",
  435. outputBuffer->CurrentConfigurationValue));
  436. // map the speed field for the old API which returned
  437. // a BOOLEAN
  438. if (!ExApi) {
  439. PUSB_NODE_CONNECTION_INFORMATION tmp =
  440. (PUSB_NODE_CONNECTION_INFORMATION) outputBuffer;
  441. tmp->LowSpeed = (outputBuffer->Speed == UsbLowSpeed)
  442. ? TRUE : FALSE;
  443. }
  444. USBH_KdPrint((2,"'Speed = %x\n", outputBuffer->Speed));
  445. USBH_KdPrint((2,"'Address = %x\n", outputBuffer->DeviceAddress));
  446. USBH_KdPrint((2,"'NumberOfOpenPipes = %d\n",
  447. outputBuffer->NumberOfOpenPipes));
  448. for(j=0; j< outputBuffer->NumberOfOpenPipes; j++) {
  449. USBH_KdPrint((2,"'Max Packet %x\n",
  450. outputBuffer->PipeList[j].EndpointDescriptor.wMaxPacketSize));
  451. USBH_KdPrint((2,"'Interval %x \n",
  452. outputBuffer->PipeList[j].EndpointDescriptor.bInterval));
  453. }
  454. Irp->IoStatus.Information =
  455. sizeof(USB_NODE_CONNECTION_INFORMATION) +
  456. sizeof(USB_PIPE_INFO) * outputBuffer->NumberOfOpenPipes;
  457. } else if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  458. Irp->IoStatus.Information =
  459. sizeof(USB_NODE_CONNECTION_INFORMATION);
  460. ntStatus = STATUS_SUCCESS;
  461. }
  462. } else { //no device object
  463. // This assert is no longer valid because we now support
  464. // displaying the UI on device enumeration failure.
  465. //
  466. // USBH_ASSERT(portData->ConnectionStatus == NoDeviceConnected ||
  467. // portData->ConnectionStatus == DeviceCausedOvercurrent);
  468. outputBuffer->ConnectionStatus = portData->ConnectionStatus;
  469. Irp->IoStatus.Information =
  470. sizeof(USB_NODE_CONNECTION_INFORMATION);
  471. ntStatus = STATUS_SUCCESS;
  472. }
  473. break;
  474. }
  475. portData++;
  476. } /* for */
  477. } else {
  478. ntStatus = STATUS_BUFFER_TOO_SMALL;
  479. }
  480. USBH_CompleteIrp(Irp, ntStatus);
  481. return ntStatus;
  482. }
  483. NTSTATUS
  484. USBH_IoctlGetNodeConnectionAttributes(
  485. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  486. IN PIRP Irp
  487. )
  488. /* ++
  489. *
  490. * Description:
  491. *
  492. * Arguments:
  493. *
  494. * Return:
  495. *
  496. * NTSTATUS
  497. *
  498. * -- */
  499. {
  500. NTSTATUS ntStatus = STATUS_SUCCESS;
  501. PIO_STACK_LOCATION ioStack;
  502. PUSB_NODE_CONNECTION_ATTRIBUTES outputBuffer;
  503. ULONG outputBufferLength, length, i;
  504. PPORT_DATA portData;
  505. PAGED_CODE();
  506. USBH_KdPrint((2,"'USBH_IoctlGetNodeConnectionInformation\n"));
  507. portData = DeviceExtensionHub->PortData;
  508. //
  509. // Get a pointer to the current location in the Irp. This is where
  510. // the function codes and parameters are located.
  511. //
  512. ioStack = IoGetCurrentIrpStackLocation(Irp);
  513. //
  514. // Get the pointer to the input/output buffer and it's length
  515. //
  516. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  517. outputBuffer = (PUSB_NODE_CONNECTION_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer;
  518. if (outputBufferLength >= sizeof(USB_NODE_CONNECTION_ATTRIBUTES)) {
  519. ULONG index;
  520. USBH_KdPrint((2,"'Connection = %d\n", outputBuffer->ConnectionIndex));
  521. // Clear the buffer in case we don't call USBD_GetDeviceInformation
  522. // below, but make sure to keep the ConnectionIndex!
  523. index = outputBuffer->ConnectionIndex;
  524. RtlZeroMemory(outputBuffer, outputBufferLength);
  525. outputBuffer->ConnectionIndex = index;
  526. ntStatus = STATUS_INVALID_PARAMETER;
  527. for(i=1; i<=DeviceExtensionHub->HubDescriptor->bNumberOfPorts; i++) {
  528. if (i == outputBuffer->ConnectionIndex) {
  529. length = sizeof(USB_NODE_CONNECTION_ATTRIBUTES);
  530. outputBuffer->ConnectionStatus =
  531. portData->ConnectionStatus;
  532. USBH_KdPrint((2,"'outputbuffer = %x\n", outputBuffer));
  533. // map extended hub info here
  534. outputBuffer->PortAttributes = portData->PortAttributes;
  535. Irp->IoStatus.Information =
  536. sizeof(USB_NODE_CONNECTION_ATTRIBUTES);
  537. ntStatus = STATUS_SUCCESS;
  538. break;
  539. }
  540. portData++;
  541. } /* for */
  542. } else {
  543. ntStatus = STATUS_BUFFER_TOO_SMALL;
  544. }
  545. USBH_CompleteIrp(Irp, ntStatus);
  546. return ntStatus;
  547. }
  548. NTSTATUS
  549. USBH_IoctlHubSymbolicName(
  550. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  551. IN PIRP Irp
  552. )
  553. /* ++
  554. *
  555. * Description:
  556. *
  557. * Takes as input and output a pointer to the following structure:
  558. *
  559. * typedef struct _USB_HUB_NAME {
  560. * ULONG ActualLength; // OUTPUT
  561. * WCHAR HubName[1]; // OUTPUT
  562. * } USB_HUB_NAME;
  563. *
  564. * Arguments:
  565. *
  566. * ActualLength - The structure size in bytes necessary to hold the NULL
  567. * terminated symbolic link name. This includes the entire structure, not
  568. * just the name.
  569. *
  570. * NodeName - The UNICODE NULL terminated symbolic link name of the external
  571. * hub attached to the port. If there is no external hub attached to the port
  572. * a single NULL is returned.
  573. *
  574. * Return:
  575. *
  576. * NTSTATUS
  577. *
  578. * -- */
  579. {
  580. NTSTATUS ntStatus = STATUS_SUCCESS;
  581. PIO_STACK_LOCATION ioStack;
  582. PUSB_HUB_NAME outputBuffer;
  583. ULONG outputBufferLength;
  584. PAGED_CODE();
  585. // Get a pointer to the current location in the Irp. This is where
  586. // the function codes and parameters are located.
  587. //
  588. ioStack = IoGetCurrentIrpStackLocation(Irp);
  589. // Get the pointer to the input/output buffer and it's length
  590. //
  591. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  592. outputBuffer = (PUSB_HUB_NAME) Irp->AssociatedIrp.SystemBuffer;
  593. // Make sure that the output buffer is large enough for the base
  594. // structure that will be returned.
  595. //
  596. if (outputBufferLength < sizeof(USB_HUB_NAME)) {
  597. ntStatus = STATUS_BUFFER_TOO_SMALL;
  598. goto GetHubDone;
  599. }
  600. if ((DeviceExtensionPort->PortPdoFlags & PORTPDO_DEVICE_IS_HUB) &&
  601. (DeviceExtensionPort->PortPdoFlags & PORTPDO_STARTED) &&
  602. (DeviceExtensionPort->PortPdoFlags & PORTPDO_SYM_LINK)) {
  603. PUNICODE_STRING hubNameUnicodeString;
  604. ULONG length, offset=0;
  605. WCHAR *pwch;
  606. // Device is a hub, get the name of the hub
  607. //
  608. hubNameUnicodeString = &DeviceExtensionPort->SymbolicLinkName;
  609. // assuming the string is \n\name strip of '\n\' where
  610. // n is zero or more chars
  611. pwch = &hubNameUnicodeString->Buffer[0];
  612. USBH_ASSERT(*pwch == '\\');
  613. if (*pwch == '\\') {
  614. pwch++;
  615. while (*pwch != '\\' && *pwch) {
  616. pwch++;
  617. }
  618. USBH_ASSERT(*pwch == '\\');
  619. if (*pwch == '\\') {
  620. pwch++;
  621. }
  622. offset = (ULONG)((PUCHAR)pwch -
  623. (PUCHAR)&hubNameUnicodeString->Buffer[0]);
  624. }
  625. // Strip off the '\DosDevices\' prefix.
  626. // Length does not include a terminating NULL.
  627. //
  628. length = hubNameUnicodeString->Length - offset;
  629. RtlZeroMemory(outputBuffer, outputBufferLength);
  630. if (outputBufferLength >= length +
  631. sizeof(USB_HUB_NAME)) {
  632. RtlCopyMemory(&outputBuffer->HubName[0],
  633. &hubNameUnicodeString->Buffer[offset/2],
  634. length);
  635. Irp->IoStatus.Information = length+
  636. sizeof(USB_HUB_NAME);
  637. outputBuffer->ActualLength = (ULONG)Irp->IoStatus.Information;
  638. ntStatus = STATUS_SUCCESS;
  639. } else {
  640. // Output buffer is too small to hold the entire
  641. // string. Return just the length needed to hold
  642. // the entire string.
  643. //
  644. outputBuffer->ActualLength =
  645. length + sizeof(USB_HUB_NAME);
  646. outputBuffer->HubName[0] = (WCHAR)0;
  647. Irp->IoStatus.Information = sizeof(USB_HUB_NAME);
  648. }
  649. } else {
  650. // Device is not a hub or does not currently have a symbolic link
  651. // allocated, just return a NULL terminated string.
  652. //
  653. outputBuffer->ActualLength = sizeof(USB_HUB_NAME);
  654. outputBuffer->HubName[0] = 0;
  655. Irp->IoStatus.Information = sizeof(USB_HUB_NAME);
  656. }
  657. GetHubDone:
  658. USBH_CompleteIrp(Irp, ntStatus);
  659. return ntStatus;
  660. }
  661. NTSTATUS
  662. USBH_IoctlGetNodeName(
  663. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  664. IN PIRP Irp
  665. )
  666. /* ++
  667. *
  668. * Description:
  669. *
  670. * Takes as input and output a pointer to the following structure:
  671. *
  672. * typedef struct _USB_NODE_CONNECTION_NAME {
  673. * ULONG ConnectionIndex; // INPUT
  674. * ULONG ActualLength; // OUTPUT
  675. * WCHAR NodeName[1]; // OUTPUT
  676. * } USB_NODE_CONNECTION_NAME;
  677. *
  678. * Arguments:
  679. *
  680. * ConnectionIndex - The one-based port index to which a device is attached.
  681. * If an external hub is attached to this port, the symbolic link name of the
  682. * hub will be returned, if there is sufficient buffer space.
  683. *
  684. * ActualLength - The structure size in bytes necessary to hold the NULL
  685. * terminated symbolic link name. This includes the entire structure, not
  686. * just the name.
  687. *
  688. * NodeName - The UNICODE NULL terminated symbolic link name of the external
  689. * hub attached to the port. If there is no external hub attached to the port
  690. * a single NULL is returned.
  691. *
  692. * Return:
  693. *
  694. * NTSTATUS
  695. *
  696. * -- */
  697. {
  698. NTSTATUS ntStatus = STATUS_SUCCESS;
  699. PIO_STACK_LOCATION ioStack;
  700. PUSB_NODE_CONNECTION_NAME outputBuffer;
  701. ULONG outputBufferLength;
  702. PPORT_DATA portData;
  703. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  704. PAGED_CODE();
  705. USBH_KdPrint((2,"'USBH_IoctlGetNodeName\n"));
  706. // Get a pointer to the current location in the Irp. This is where
  707. // the function codes and parameters are located.
  708. //
  709. ioStack = IoGetCurrentIrpStackLocation(Irp);
  710. // Get the pointer to the input/output buffer and it's length
  711. //
  712. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  713. outputBuffer = (PUSB_NODE_CONNECTION_NAME) Irp->AssociatedIrp.SystemBuffer;
  714. // Make sure that the output buffer is large enough for the base
  715. // structure that will be returned.
  716. //
  717. if (outputBufferLength < sizeof(USB_NODE_CONNECTION_NAME)) {
  718. ntStatus = STATUS_BUFFER_TOO_SMALL;
  719. goto GetNodeNameDone;
  720. }
  721. USBH_KdPrint((2,"'Connection = %d\n", outputBuffer->ConnectionIndex));
  722. // Make sure that the (one-based) port index is valid.
  723. //
  724. if ((outputBuffer->ConnectionIndex == 0) ||
  725. (outputBuffer->ConnectionIndex >
  726. DeviceExtensionHub->HubDescriptor->bNumberOfPorts)) {
  727. ntStatus = STATUS_INVALID_PARAMETER;
  728. goto GetNodeNameDone;
  729. }
  730. // Get a pointer to the data associated with the specified (one-based) port
  731. //
  732. portData = &DeviceExtensionHub->PortData[outputBuffer->ConnectionIndex - 1];
  733. if (portData->DeviceObject) {
  734. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  735. if ((deviceExtensionPort->PortPdoFlags & PORTPDO_DEVICE_IS_HUB) &&
  736. (deviceExtensionPort->PortPdoFlags & PORTPDO_STARTED) &&
  737. (deviceExtensionPort->PortPdoFlags & PORTPDO_SYM_LINK)) {
  738. PUNICODE_STRING nodeNameUnicodeString;
  739. ULONG length, offset=0;
  740. WCHAR *pwch;
  741. // Device is a hub, get the name of the hub
  742. //
  743. nodeNameUnicodeString = &deviceExtensionPort->SymbolicLinkName;
  744. // assuming the string is \n\name strip of '\n\' where
  745. // n is zero or more chars
  746. pwch = &nodeNameUnicodeString->Buffer[0];
  747. USBH_ASSERT(*pwch == '\\');
  748. if (*pwch == '\\') {
  749. pwch++;
  750. while (*pwch != '\\' && *pwch) {
  751. pwch++;
  752. }
  753. USBH_ASSERT(*pwch == '\\');
  754. if (*pwch == '\\') {
  755. pwch++;
  756. }
  757. offset = (ULONG)((PUCHAR)pwch -
  758. (PUCHAR)&nodeNameUnicodeString->Buffer[0]);
  759. }
  760. // Strip off the '\DosDevices\' prefix.
  761. // Length does not include a terminating NULL.
  762. //
  763. length = nodeNameUnicodeString->Length - offset;
  764. RtlZeroMemory(outputBuffer, outputBufferLength);
  765. if (outputBufferLength >= length +
  766. sizeof(USB_NODE_CONNECTION_NAME)) {
  767. RtlCopyMemory(&outputBuffer->NodeName[0],
  768. &nodeNameUnicodeString->Buffer[offset/2],
  769. length);
  770. Irp->IoStatus.Information = length+
  771. sizeof(USB_NODE_CONNECTION_NAME);
  772. outputBuffer->ActualLength = (ULONG)Irp->IoStatus.Information;
  773. ntStatus = STATUS_SUCCESS;
  774. } else {
  775. // Output buffer is too small to hold the entire
  776. // string. Return just the length needed to hold
  777. // the entire string.
  778. //
  779. outputBuffer->ActualLength =
  780. length + sizeof(USB_NODE_CONNECTION_NAME);
  781. outputBuffer->NodeName[0] = (WCHAR)0;
  782. Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_NAME);
  783. }
  784. } else {
  785. // Device is not a hub or does not currently have a symbolic link
  786. // allocated, just return a NULL terminated string.
  787. //
  788. outputBuffer->ActualLength = sizeof(USB_NODE_CONNECTION_NAME);
  789. outputBuffer->NodeName[0] = 0;
  790. Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_NAME);
  791. }
  792. } else {
  793. // No device attached, just return a NULL terminated string.
  794. Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_NAME);
  795. outputBuffer->ActualLength = sizeof(USB_NODE_CONNECTION_NAME);
  796. outputBuffer->NodeName[0] = 0;
  797. }
  798. GetNodeNameDone:
  799. USBH_CompleteIrp(Irp, ntStatus);
  800. return ntStatus;
  801. }
  802. NTSTATUS
  803. USBH_PdoIoctlGetPortStatus(
  804. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  805. IN PIRP Irp
  806. )
  807. /*
  808. * Description:
  809. *
  810. * Arguments:
  811. *
  812. * Return:
  813. *
  814. * NTSTATUS
  815. *
  816. * -- */
  817. {
  818. NTSTATUS ntStatus = STATUS_SUCCESS;
  819. PIO_STACK_LOCATION ioStackLocation; // our stack location
  820. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  821. PDEVICE_OBJECT deviceObject;
  822. PPORT_DATA portData;
  823. PULONG portStatus;
  824. PAGED_CODE();
  825. USBH_KdPrint((2,"'USBH_PdoIoctlGetPortStatus DeviceExtension %x Irp %x\n",
  826. DeviceExtensionPort, Irp));
  827. deviceExtensionHub = DeviceExtensionPort->DeviceExtensionHub;
  828. USBH_KdPrint((2,"'***WAIT hub mutex %x\n", deviceExtensionHub));
  829. USBH_INC_PENDING_IO_COUNT(deviceExtensionHub);
  830. KeWaitForSingleObject(&deviceExtensionHub->HubMutex,
  831. Executive,
  832. KernelMode,
  833. FALSE,
  834. NULL);
  835. USBH_KdPrint((2,"'***WAIT hub mutex done %x\n", deviceExtensionHub));
  836. portData = &deviceExtensionHub->PortData[DeviceExtensionPort->PortNumber - 1];
  837. deviceObject = DeviceExtensionPort->PortPhysicalDeviceObject;
  838. ioStackLocation = IoGetCurrentIrpStackLocation(Irp);
  839. portStatus = ioStackLocation->Parameters.Others.Argument1;
  840. USBH_ASSERT(portStatus != NULL);
  841. *portStatus = 0;
  842. // Refresh our notion of what the port status actually is.
  843. ntStatus = USBH_SyncGetPortStatus(deviceExtensionHub,
  844. DeviceExtensionPort->PortNumber,
  845. (PUCHAR) &portData->PortState,
  846. sizeof(portData->PortState));
  847. if (DeviceExtensionPort->PortPhysicalDeviceObject == portData->DeviceObject) {
  848. // translate hup port status bits
  849. if (portData->PortState.PortStatus & PORT_STATUS_ENABLE) {
  850. *portStatus |= USBD_PORT_ENABLED;
  851. }
  852. if (portData->PortState.PortStatus & PORT_STATUS_CONNECT ) {
  853. *portStatus |= USBD_PORT_CONNECTED;
  854. }
  855. }
  856. USBH_KdPrint((2,"'***RELEASE hub mutex %x\n", deviceExtensionHub));
  857. KeReleaseSemaphore(&deviceExtensionHub->HubMutex,
  858. LOW_REALTIME_PRIORITY,
  859. 1,
  860. FALSE);
  861. USBH_DEC_PENDING_IO_COUNT(deviceExtensionHub);
  862. USBH_CompleteIrp(Irp, ntStatus);
  863. return ntStatus;
  864. }
  865. NTSTATUS
  866. USBH_PdoIoctlEnablePort(
  867. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  868. IN PIRP Irp
  869. )
  870. /*
  871. * Description:
  872. *
  873. * Arguments:
  874. *
  875. * Return:
  876. *
  877. * NTSTATUS
  878. *
  879. * -- */
  880. {
  881. NTSTATUS ntStatus = STATUS_SUCCESS;
  882. PIO_STACK_LOCATION ioStackLocation; // our stack location
  883. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  884. PDEVICE_OBJECT deviceObject;
  885. PPORT_DATA portData;
  886. PORT_STATE portState;
  887. USBH_KdPrint((2,"'USBH_PdoIoctlEnablePort DeviceExtension %x Irp %x\n",
  888. DeviceExtensionPort, Irp));
  889. deviceExtensionHub = DeviceExtensionPort->DeviceExtensionHub;
  890. USBH_KdPrint((2,"'***WAIT hub mutex %x\n", deviceExtensionHub));
  891. USBH_INC_PENDING_IO_COUNT(deviceExtensionHub);
  892. KeWaitForSingleObject(&deviceExtensionHub->HubMutex,
  893. Executive,
  894. KernelMode,
  895. FALSE,
  896. NULL);
  897. USBH_KdPrint((2,"'***WAIT hub mutex done %x\n", deviceExtensionHub));
  898. portData = &deviceExtensionHub->PortData[DeviceExtensionPort->PortNumber - 1];
  899. deviceObject = DeviceExtensionPort->PortPhysicalDeviceObject;
  900. ioStackLocation = IoGetCurrentIrpStackLocation(Irp);
  901. // validate that there is actually a device still conected
  902. ntStatus = USBH_SyncGetPortStatus(deviceExtensionHub,
  903. DeviceExtensionPort->PortNumber,
  904. (PUCHAR) &portState,
  905. sizeof(portState));
  906. if ((NT_SUCCESS(ntStatus) &&
  907. (portState.PortStatus & PORT_STATUS_CONNECT))) {
  908. LOGENTRY(LOG_PNP, "estE",
  909. deviceExtensionHub,
  910. DeviceExtensionPort->PortNumber,
  911. 0);
  912. ntStatus = USBH_SyncEnablePort(deviceExtensionHub,
  913. DeviceExtensionPort->PortNumber);
  914. } else {
  915. // error or no device connected or
  916. // can't be sure, fail the request
  917. LOGENTRY(LOG_PNP, "estx",
  918. deviceExtensionHub,
  919. DeviceExtensionPort->PortNumber,
  920. 0);
  921. ntStatus = STATUS_UNSUCCESSFUL;
  922. }
  923. USBH_KdPrint((2,"'***RELEASE hub mutex %x\n", deviceExtensionHub));
  924. KeReleaseSemaphore(&deviceExtensionHub->HubMutex,
  925. LOW_REALTIME_PRIORITY,
  926. 1,
  927. FALSE);
  928. USBH_DEC_PENDING_IO_COUNT(deviceExtensionHub);
  929. USBH_CompleteIrp(Irp, ntStatus);
  930. return ntStatus;
  931. }
  932. NTSTATUS
  933. USBH_IoctlGetDescriptorForPDO(
  934. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  935. IN PIRP Irp
  936. )
  937. /* ++
  938. *
  939. * Description:
  940. *
  941. * Arguments:
  942. *
  943. * Return:
  944. *
  945. * NTSTATUS
  946. *
  947. * -- */
  948. {
  949. NTSTATUS ntStatus = STATUS_SUCCESS;
  950. PIO_STACK_LOCATION ioStack;
  951. ULONG outputBufferLength;
  952. PUCHAR outputBuffer;
  953. PUSB_DESCRIPTOR_REQUEST request;
  954. PPORT_DATA portData;
  955. ULONG i;
  956. PAGED_CODE();
  957. USBH_KdPrint((2,"'USBH_IoctlDescriptorRequest\n"));
  958. portData = DeviceExtensionHub->PortData;
  959. //
  960. // Get a pointer to the current location in the Irp. This is where
  961. // the function codes and parameters are located.
  962. //
  963. ioStack = IoGetCurrentIrpStackLocation(Irp);
  964. //
  965. // Get the pointer to the input/output buffer and it's length
  966. //
  967. outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
  968. if (outputBufferLength < sizeof(USB_DESCRIPTOR_REQUEST)) {
  969. ntStatus = STATUS_BUFFER_TOO_SMALL;
  970. goto USBH_IoctlGetDescriptorForPDO_Complete;
  971. }
  972. request = (PUSB_DESCRIPTOR_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  973. outputBuffer = &request->Data[0];
  974. //
  975. // do some parameter checking
  976. //
  977. // the wLength in the setup packet better be the size of the
  978. // outputbuffer minus header
  979. //
  980. if (request->SetupPacket.wLength >
  981. outputBufferLength - sizeof(USB_DESCRIPTOR_REQUEST)) {
  982. ntStatus = STATUS_BUFFER_TOO_SMALL;
  983. goto USBH_IoctlGetDescriptorForPDO_Complete;
  984. } else {
  985. // request won't return more than wLength
  986. outputBufferLength = request->SetupPacket.wLength;
  987. }
  988. // return invalid parameter if conn index is out
  989. // of bounds
  990. ntStatus = STATUS_INVALID_PARAMETER;
  991. for(i=1; i<=DeviceExtensionHub->HubDescriptor->bNumberOfPorts; i++) {
  992. if (i == request->ConnectionIndex) {
  993. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  994. // make sure we have a valid devobj for this index
  995. if (portData->DeviceObject == NULL) {
  996. goto USBH_IoctlGetDescriptorForPDO_Complete;
  997. }
  998. deviceExtensionPort =
  999. portData->DeviceObject->DeviceExtension;
  1000. if (request->SetupPacket.wValue ==
  1001. ((USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | 0) &&
  1002. outputBufferLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
  1003. //
  1004. // Only wants the basic configuration descriptor without the
  1005. // rest of them tacked on (ie. interface, endpoint descriptors).
  1006. //
  1007. USBH_ASSERT(deviceExtensionPort->ExtensionType == EXTENSION_TYPE_PORT);
  1008. RtlCopyMemory(outputBuffer,
  1009. &deviceExtensionPort->ConfigDescriptor,
  1010. outputBufferLength);
  1011. Irp->IoStatus.Information =
  1012. outputBufferLength + sizeof(USB_DESCRIPTOR_REQUEST);
  1013. ntStatus = STATUS_SUCCESS;
  1014. } else {
  1015. PURB urb;
  1016. //
  1017. // OK send the request
  1018. //
  1019. USBH_KdPrint((2,"'sending descriptor request for ioclt\n"));
  1020. //
  1021. // Allocate an Urb and descriptor buffer.
  1022. //
  1023. urb = UsbhExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  1024. if (urb) {
  1025. UsbBuildGetDescriptorRequest(urb,
  1026. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1027. request->SetupPacket.wValue >> 8,
  1028. request->SetupPacket.wValue & 0xff,
  1029. 0,
  1030. outputBuffer,
  1031. NULL,
  1032. outputBufferLength,
  1033. NULL);
  1034. RtlCopyMemory(&urb->UrbControlDescriptorRequest.Reserved1,
  1035. &request->SetupPacket.bmRequest,
  1036. 8);
  1037. ntStatus = USBH_SyncSubmitUrb(deviceExtensionPort->PortPhysicalDeviceObject, urb);
  1038. Irp->IoStatus.Information =
  1039. urb->UrbControlDescriptorRequest.TransferBufferLength +
  1040. sizeof(USB_DESCRIPTOR_REQUEST);
  1041. UsbhExFreePool(urb);
  1042. } else {
  1043. USBH_KdBreak(("SyncGetDeviceConfigurationDescriptor fail alloc Urb\n"));
  1044. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1045. }
  1046. }
  1047. break;
  1048. }
  1049. portData++;
  1050. }
  1051. USBH_IoctlGetDescriptorForPDO_Complete:
  1052. USBH_CompleteIrp(Irp, ntStatus);
  1053. return ntStatus;
  1054. }
  1055. NTSTATUS
  1056. USBH_PdoIoctlResetPort(
  1057. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  1058. IN PIRP Irp
  1059. )
  1060. /*
  1061. * Description:
  1062. *
  1063. * driver is requesting us to reset the port to which the device
  1064. * is attached.
  1065. *
  1066. * Arguments:
  1067. *
  1068. * Return:
  1069. *
  1070. * NTSTATUS
  1071. *
  1072. * -- */
  1073. {
  1074. NTSTATUS ntStatus = STATUS_SUCCESS;
  1075. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  1076. PPORT_DATA portData;
  1077. PAGED_CODE();
  1078. USBH_KdPrint((2,"'USBH_PdoIoctlResetPort DeviceExtension %x Irp %x\n",
  1079. DeviceExtensionPort, Irp));
  1080. deviceExtensionHub = DeviceExtensionPort->DeviceExtensionHub;
  1081. if (!deviceExtensionHub) {
  1082. ntStatus = STATUS_UNSUCCESSFUL;
  1083. goto USBH_PdoIoctlResetPortExit;
  1084. }
  1085. USBH_KdPrint((2,"'***WAIT hub mutex %x\n", deviceExtensionHub));
  1086. USBH_INC_PENDING_IO_COUNT(deviceExtensionHub);
  1087. KeWaitForSingleObject(&deviceExtensionHub->HubMutex,
  1088. Executive,
  1089. KernelMode,
  1090. FALSE,
  1091. NULL);
  1092. USBH_KdPrint((2,"'***WAIT hub mutex done %x\n", deviceExtensionHub));
  1093. portData =
  1094. &deviceExtensionHub->PortData[DeviceExtensionPort->PortNumber - 1];
  1095. LOGENTRY(LOG_PNP, "Drst", deviceExtensionHub,
  1096. DeviceExtensionPort->PortPhysicalDeviceObject,
  1097. portData->DeviceObject);
  1098. if (DeviceExtensionPort->PortPhysicalDeviceObject ==
  1099. portData->DeviceObject && DeviceExtensionPort->DeviceData != NULL) {
  1100. #ifdef USB2
  1101. USBD_RemoveDeviceEx(deviceExtensionHub,
  1102. DeviceExtensionPort->DeviceData,
  1103. deviceExtensionHub->RootHubPdo,
  1104. USBD_MARK_DEVICE_BUSY);
  1105. #else
  1106. USBD_RemoveDevice(DeviceExtensionPort->DeviceData,
  1107. deviceExtensionHub->RootHubPdo,
  1108. USBD_MARK_DEVICE_BUSY);
  1109. #endif
  1110. ntStatus = USBH_ResetDevice(deviceExtensionHub,
  1111. DeviceExtensionPort->PortNumber,
  1112. TRUE,
  1113. 0); // RetryIteration
  1114. } else {
  1115. ntStatus = STATUS_INVALID_PARAMETER;
  1116. }
  1117. USBH_KdPrint((1,"'Warning: driver has reset the port (%x)\n",
  1118. ntStatus));
  1119. USBH_KdPrint((2,"'***RELEASE hub mutex %x\n", deviceExtensionHub));
  1120. KeReleaseSemaphore(&deviceExtensionHub->HubMutex,
  1121. LOW_REALTIME_PRIORITY,
  1122. 1,
  1123. FALSE);
  1124. USBH_DEC_PENDING_IO_COUNT(deviceExtensionHub);
  1125. USBH_PdoIoctlResetPortExit:
  1126. // Must do this before completing the IRP because client driver may want
  1127. // to post URB transfers in the completion routine. These transfers will
  1128. // fail if this flag is still set.
  1129. DeviceExtensionPort->PortPdoFlags &= ~PORTPDO_RESET_PENDING;
  1130. USBH_CompleteIrp(Irp, ntStatus);
  1131. return ntStatus;
  1132. }
  1133. VOID
  1134. USBH_InternalCyclePort(
  1135. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  1136. IN USHORT PortNumber,
  1137. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort
  1138. )
  1139. /*
  1140. * Description:
  1141. *
  1142. * "Cycles" the requested port, i.e. causes PnP REMOVE and reenumeration
  1143. * of the device.
  1144. *
  1145. * Arguments:
  1146. *
  1147. * Return:
  1148. *
  1149. * NTSTATUS
  1150. *
  1151. * -- */
  1152. {
  1153. PPORT_DATA portData;
  1154. PWCHAR sernumbuf = NULL;
  1155. portData = &DeviceExtensionHub->PortData[PortNumber-1];
  1156. LOGENTRY(LOG_PNP, "WMIo", DeviceExtensionHub,
  1157. PortNumber,
  1158. DeviceExtensionPort);
  1159. // synchronize with QBR
  1160. USBH_KdPrint((2,"'***WAIT reset device mutex %x\n", DeviceExtensionHub));
  1161. USBH_INC_PENDING_IO_COUNT(DeviceExtensionHub);
  1162. KeWaitForSingleObject(&DeviceExtensionHub->ResetDeviceMutex,
  1163. Executive,
  1164. KernelMode,
  1165. FALSE,
  1166. NULL);
  1167. USBH_KdPrint((2,"'***WAIT reset device mutex done %x\n", DeviceExtensionHub));
  1168. {
  1169. PDEVICE_OBJECT pdo;
  1170. pdo = portData->DeviceObject;
  1171. portData->DeviceObject = NULL;
  1172. portData->ConnectionStatus = NoDeviceConnected;
  1173. if (pdo) {
  1174. // device should be present if we do this
  1175. USBH_ASSERT(PDO_EXT(pdo)->PnPFlags & PDO_PNPFLAG_DEVICE_PRESENT);
  1176. InsertTailList(&DeviceExtensionHub->DeletePdoList,
  1177. &PDO_EXT(pdo)->DeletePdoLink);
  1178. }
  1179. }
  1180. // in some overcurrent scenarios we may not have a PDO.
  1181. // this function is synchronous, so the device should have
  1182. // no tranfsers on completion
  1183. if (DeviceExtensionPort) {
  1184. USBD_RemoveDeviceEx(DeviceExtensionHub,
  1185. DeviceExtensionPort->DeviceData,
  1186. DeviceExtensionHub->RootHubPdo,
  1187. 0);
  1188. DeviceExtensionPort->DeviceData = NULL;
  1189. // this prevents resets by the client
  1190. DeviceExtensionPort->PortPdoFlags |= PORTPDO_CYCLED;
  1191. // keep ref until removeal of hub OR child
  1192. //DeviceExtensionPort->DeviceExtensionHub = NULL;
  1193. // disable the port so no traffic passes to the device until reset
  1194. USBH_SyncDisablePort(DeviceExtensionHub,
  1195. DeviceExtensionPort->PortNumber);
  1196. sernumbuf = InterlockedExchangePointer(
  1197. &DeviceExtensionPort->SerialNumberBuffer,
  1198. NULL);
  1199. }
  1200. if (sernumbuf) {
  1201. UsbhExFreePool(sernumbuf);
  1202. }
  1203. USBH_KdPrint((2,"'***RELEASE reset device mutex %x\n", DeviceExtensionHub));
  1204. KeReleaseSemaphore(&DeviceExtensionHub->ResetDeviceMutex,
  1205. LOW_REALTIME_PRIORITY,
  1206. 1,
  1207. FALSE);
  1208. USBH_DEC_PENDING_IO_COUNT(DeviceExtensionHub);
  1209. USBH_IoInvalidateDeviceRelations(DeviceExtensionHub->PhysicalDeviceObject,
  1210. BusRelations);
  1211. }
  1212. NTSTATUS
  1213. USBH_PdoIoctlCyclePort(
  1214. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  1215. IN PIRP Irp
  1216. )
  1217. /*
  1218. * Description:
  1219. *
  1220. * driver is requesting us to reset the port to which the device
  1221. * is attached.
  1222. *
  1223. * Arguments:
  1224. *
  1225. * Return:
  1226. *
  1227. * NTSTATUS
  1228. *
  1229. * -- */
  1230. {
  1231. NTSTATUS ntStatus = STATUS_SUCCESS;
  1232. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  1233. USHORT portNumber;
  1234. PAGED_CODE();
  1235. USBH_KdPrint((2,"'USBH_PdoIoctlResetPort DeviceExtension %x Irp %x\n",
  1236. DeviceExtensionPort, Irp));
  1237. deviceExtensionHub = DeviceExtensionPort->DeviceExtensionHub;
  1238. portNumber = DeviceExtensionPort->PortNumber;
  1239. USBH_InternalCyclePort(deviceExtensionHub, portNumber, DeviceExtensionPort);
  1240. USBH_CompleteIrp(Irp, ntStatus);
  1241. return ntStatus;
  1242. }
  1243. #ifdef WMI_SUPPORT
  1244. NTSTATUS
  1245. USBH_BuildConnectionNotification(
  1246. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  1247. IN USHORT PortNumber,
  1248. IN PUSB_CONNECTION_NOTIFICATION Notification
  1249. )
  1250. /*
  1251. * Description:
  1252. *
  1253. * driver is requesting us to reset the port to which the device
  1254. * is attached.
  1255. *
  1256. * Arguments:
  1257. *
  1258. * Return:
  1259. *
  1260. * NTSTATUS
  1261. *
  1262. * -- */
  1263. {
  1264. NTSTATUS ntStatus = STATUS_SUCCESS, status;
  1265. USB_CONNECTION_STATUS connectStatus;
  1266. USB_HUB_NAME hubName;
  1267. PPORT_DATA portData;
  1268. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  1269. portData =
  1270. &DeviceExtensionHub->PortData[PortNumber-1];
  1271. if (portData->DeviceObject &&
  1272. portData->ConnectionStatus != DeviceHubNestedTooDeeply) {
  1273. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  1274. connectStatus = UsbhGetConnectionStatus(deviceExtensionPort);
  1275. } else {
  1276. deviceExtensionPort = NULL;
  1277. connectStatus = portData->ConnectionStatus;
  1278. }
  1279. RtlZeroMemory(Notification, sizeof(*Notification));
  1280. Notification->ConnectionNumber = PortNumber;
  1281. if (IS_ROOT_HUB(DeviceExtensionHub)) {
  1282. hubName.ActualLength = sizeof(hubName) - sizeof(hubName.ActualLength);
  1283. status = USBHUB_GetRootHubName(DeviceExtensionHub,
  1284. &hubName.HubName,
  1285. &hubName.ActualLength);
  1286. } else {
  1287. status = USBH_SyncGetHubName(DeviceExtensionHub->TopOfStackDeviceObject,
  1288. &hubName,
  1289. sizeof(hubName));
  1290. }
  1291. USBH_KdPrint((1,"'Notification, hub name length = %d\n",
  1292. hubName.ActualLength));
  1293. if (NT_SUCCESS(status)) {
  1294. Notification->HubNameLength = hubName.ActualLength;
  1295. } else {
  1296. Notification->HubNameLength = 0;
  1297. }
  1298. switch(connectStatus) {
  1299. case DeviceFailedEnumeration:
  1300. // need to track some some reasons
  1301. if (deviceExtensionPort) {
  1302. Notification->EnumerationFailReason =
  1303. deviceExtensionPort->FailReasonId;
  1304. } else {
  1305. Notification->EnumerationFailReason = 0;
  1306. }
  1307. Notification->NotificationType = EnumerationFailure;
  1308. break;
  1309. case DeviceCausedOvercurrent:
  1310. Notification->NotificationType = OverCurrent;
  1311. break;
  1312. case DeviceNotEnoughPower:
  1313. Notification->NotificationType = InsufficentPower;
  1314. if (deviceExtensionPort) {
  1315. Notification->PowerRequested =
  1316. deviceExtensionPort->PowerRequested;
  1317. }
  1318. break;
  1319. case DeviceNotEnoughBandwidth:
  1320. Notification->NotificationType = InsufficentBandwidth;
  1321. if (deviceExtensionPort) {
  1322. Notification->RequestedBandwidth =
  1323. deviceExtensionPort->RequestedBandwidth;
  1324. }
  1325. break;
  1326. case DeviceHubNestedTooDeeply:
  1327. Notification->NotificationType = HubNestedTooDeeply;
  1328. break;
  1329. case DeviceInLegacyHub:
  1330. Notification->NotificationType = ModernDeviceInLegacyHub;
  1331. break;
  1332. case DeviceGeneralFailure:
  1333. default:
  1334. // nothing wrong?
  1335. ntStatus = STATUS_UNSUCCESSFUL;
  1336. }
  1337. return ntStatus;
  1338. }
  1339. #endif
  1340. NTSTATUS
  1341. USBH_PdoEvent(
  1342. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  1343. IN USHORT PortNumber
  1344. )
  1345. /*
  1346. * Description:
  1347. *
  1348. * Triggers a WMI event based on the current connection status of the port
  1349. *
  1350. * Arguments:
  1351. *
  1352. * Return:
  1353. *
  1354. * NTSTATUS
  1355. *
  1356. * -- */
  1357. {
  1358. NTSTATUS ntStatus = STATUS_SUCCESS;
  1359. #ifdef WMI_SUPPORT
  1360. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  1361. PPORT_DATA portData;
  1362. PUSB_CONNECTION_NOTIFICATION notification;
  1363. portData =
  1364. &DeviceExtensionHub->PortData[PortNumber-1];
  1365. if (portData->DeviceObject) {
  1366. deviceExtensionPort = portData->DeviceObject->DeviceExtension;
  1367. }
  1368. USBH_KdPrint((1,"'Fire WMI Event for Port Ext %x on hub ext %x\n",
  1369. deviceExtensionPort, DeviceExtensionHub));
  1370. LOGENTRY(LOG_PNP, "WMIe", DeviceExtensionHub,
  1371. deviceExtensionPort,
  1372. 0);
  1373. notification = ExAllocatePoolWithTag(PagedPool,
  1374. sizeof(USB_CONNECTION_NOTIFICATION),
  1375. USBHUB_HEAP_TAG);
  1376. if (notification) {
  1377. ntStatus = USBH_BuildConnectionNotification(
  1378. DeviceExtensionHub,
  1379. PortNumber,
  1380. notification);
  1381. if (NT_SUCCESS(ntStatus)) {
  1382. ntStatus = WmiFireEvent(
  1383. DeviceExtensionHub->FunctionalDeviceObject,
  1384. (LPGUID)&GUID_USB_WMI_STD_NOTIFICATION,
  1385. 0,
  1386. sizeof(*notification),
  1387. notification);
  1388. } else {
  1389. // Since we did not call WmiFireEvent then we must free the buffer
  1390. // ourselves.
  1391. ExFreePool(notification);
  1392. }
  1393. } else {
  1394. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1395. }
  1396. #endif /* WMI_SUPPORT */
  1397. return ntStatus;
  1398. }
  1399. #ifdef WMI_SUPPORT
  1400. NTSTATUS
  1401. USBH_SystemControl (
  1402. IN PDEVICE_EXTENSION_FDO DeviceExtensionFdo,
  1403. IN PIRP Irp
  1404. )
  1405. /*++
  1406. Routine Description
  1407. We have just received a System Control IRP.
  1408. Assume that this is a WMI IRP and
  1409. call into the WMI system library and let it handle this IRP for us.
  1410. --*/
  1411. {
  1412. SYSCTL_IRP_DISPOSITION IrpDisposition;
  1413. NTSTATUS ntStatus = STATUS_SUCCESS;
  1414. ntStatus = WmiSystemControl(
  1415. &DeviceExtensionFdo->WmiLibInfo,
  1416. DeviceExtensionFdo->FunctionalDeviceObject,
  1417. Irp,
  1418. &IrpDisposition);
  1419. switch (IrpDisposition)
  1420. {
  1421. case IrpProcessed:
  1422. {
  1423. //
  1424. // This irp has been processed and may be completed or pending.
  1425. break;
  1426. }
  1427. case IrpNotCompleted:
  1428. {
  1429. //
  1430. // This irp has not been completed, but has been fully processed.
  1431. // we will complete it now
  1432. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1433. break;
  1434. }
  1435. case IrpForward:
  1436. case IrpNotWmi:
  1437. {
  1438. //
  1439. // This irp is either not a WMI irp or is a WMI irp targetted
  1440. // at a device lower in the stack.
  1441. ntStatus = USBH_PassIrp(Irp, DeviceExtensionFdo->TopOfStackDeviceObject);
  1442. break;
  1443. }
  1444. default:
  1445. {
  1446. //
  1447. // We really should never get here, but if we do just forward....
  1448. ASSERT(FALSE);
  1449. ntStatus = USBH_PassIrp(Irp, DeviceExtensionFdo->TopOfStackDeviceObject);
  1450. break;
  1451. }
  1452. }
  1453. return(ntStatus);
  1454. }
  1455. NTSTATUS
  1456. USBH_PortSystemControl (
  1457. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  1458. IN PIRP Irp
  1459. )
  1460. /*++
  1461. Routine Description
  1462. We have just received a System Control IRP.
  1463. Assume that this is a WMI IRP and
  1464. call into the WMI system library and let it handle this IRP for us.
  1465. --*/
  1466. {
  1467. SYSCTL_IRP_DISPOSITION IrpDisposition;
  1468. NTSTATUS ntStatus = STATUS_SUCCESS;
  1469. ntStatus = WmiSystemControl(
  1470. &DeviceExtensionPort->WmiLibInfo,
  1471. DeviceExtensionPort->PortPhysicalDeviceObject,
  1472. Irp,
  1473. &IrpDisposition);
  1474. switch (IrpDisposition)
  1475. {
  1476. case IrpNotWmi:
  1477. // Don't change status of IRP we don't know about.
  1478. ntStatus = Irp->IoStatus.Status;
  1479. // fall through
  1480. case IrpNotCompleted:
  1481. case IrpForward:
  1482. default:
  1483. USBH_CompleteIrp(Irp, ntStatus);
  1484. break;
  1485. case IrpProcessed:
  1486. // Don't complete the IRP in this case.
  1487. break;
  1488. }
  1489. return(ntStatus);
  1490. }
  1491. PDEVICE_EXTENSION_PORT
  1492. USBH_GetPortPdoExtension(
  1493. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  1494. IN ULONG PortNumber
  1495. )
  1496. /*
  1497. * Description:
  1498. *
  1499. * Arguments:
  1500. *
  1501. * Return:
  1502. *
  1503. * NTSTATUS
  1504. *
  1505. * -- */
  1506. {
  1507. PPORT_DATA portData;
  1508. USHORT nextPortNumber;
  1509. USHORT numberOfPorts;
  1510. portData = DeviceExtensionHub->PortData;
  1511. //
  1512. // hub descriptor will be null if the hub is already stopped
  1513. //
  1514. if (portData &&
  1515. DeviceExtensionHub->HubDescriptor) {
  1516. numberOfPorts = DeviceExtensionHub->HubDescriptor->bNumberOfPorts;
  1517. for (nextPortNumber = 1;
  1518. nextPortNumber <= numberOfPorts;
  1519. nextPortNumber++, portData++) {
  1520. USBH_KdPrint((1,"'portdata %x, do %x\n", portData, portData->DeviceObject));
  1521. if (PortNumber == nextPortNumber) {
  1522. if (portData->DeviceObject)
  1523. return portData->DeviceObject->DeviceExtension;
  1524. else
  1525. return NULL;
  1526. }
  1527. }
  1528. }
  1529. return NULL;
  1530. }
  1531. VOID
  1532. USBH_CheckLeafHubsIdle(
  1533. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub
  1534. )
  1535. /* ++
  1536. *
  1537. * Description:
  1538. *
  1539. * This function walks the chain of hubs downstream from the specified hub,
  1540. * and idles the leaf hubs if ready.
  1541. *
  1542. * Arguments:
  1543. *
  1544. * DeviceExtensionHub
  1545. *
  1546. * Return:
  1547. *
  1548. * NTSTATUS
  1549. *
  1550. * -- */
  1551. {
  1552. PDEVICE_EXTENSION_PORT childDeviceExtensionPort;
  1553. PDEVICE_EXTENSION_HUB childDeviceExtensionHub;
  1554. BOOLEAN bHaveChildrenHubs = FALSE;
  1555. ULONG i;
  1556. PAGED_CODE();
  1557. // Ensure that child port configuration does not change while in this
  1558. // function, i.e. don't allow QBR.
  1559. // USBH_KdPrint((2,"'***WAIT reset device mutex %x\n", DeviceExtensionHub));
  1560. // USBH_INC_PENDING_IO_COUNT(DeviceExtensionHub);
  1561. // KeWaitForSingleObject(&DeviceExtensionHub->ResetDeviceMutex,
  1562. // Executive,
  1563. // KernelMode,
  1564. // FALSE,
  1565. // NULL);
  1566. // USBH_KdPrint((2,"'***WAIT reset device mutex done %x\n", DeviceExtensionHub));
  1567. for (i = 0; i < DeviceExtensionHub->HubDescriptor->bNumberOfPorts; i++) {
  1568. if (DeviceExtensionHub->PortData[i].DeviceObject) {
  1569. childDeviceExtensionPort = DeviceExtensionHub->PortData[i].DeviceObject->DeviceExtension;
  1570. if (childDeviceExtensionPort->PortPdoFlags & PORTPDO_DEVICE_IS_HUB) {
  1571. PDRIVER_OBJECT hubDriver;
  1572. PDEVICE_OBJECT childHubPdo, childHubFdo;
  1573. // We have a child hub. This means that we are not a leaf hub.
  1574. // Indicate this and recurse down to the child hub.
  1575. bHaveChildrenHubs = TRUE;
  1576. hubDriver = DeviceExtensionHub->FunctionalDeviceObject->DriverObject;
  1577. childHubPdo = childDeviceExtensionPort->PortPhysicalDeviceObject;
  1578. do {
  1579. childHubFdo = childHubPdo->AttachedDevice;
  1580. childHubPdo = childHubFdo;
  1581. } while (childHubFdo->DriverObject != hubDriver);
  1582. childDeviceExtensionHub = childHubFdo->DeviceExtension;
  1583. USBH_CheckLeafHubsIdle(childDeviceExtensionHub);
  1584. }
  1585. }
  1586. }
  1587. // USBH_KdPrint((2,"'***RELEASE reset device mutex %x\n", DeviceExtensionHub));
  1588. // KeReleaseSemaphore(&DeviceExtensionHub->ResetDeviceMutex,
  1589. // LOW_REALTIME_PRIORITY,
  1590. // 1,
  1591. // FALSE);
  1592. //
  1593. // USBH_DEC_PENDING_IO_COUNT(DeviceExtensionHub);
  1594. if (!bHaveChildrenHubs) {
  1595. // If this hub has no children then it is a leaf hub. See if
  1596. // it is ready to be idled out.
  1597. USBH_CheckHubIdle(DeviceExtensionHub);
  1598. }
  1599. }
  1600. //
  1601. // WMI System Call back functions
  1602. //
  1603. NTSTATUS
  1604. USBH_SetWmiDataBlock(
  1605. IN PDEVICE_OBJECT DeviceObject,
  1606. IN PIRP Irp,
  1607. IN ULONG GuidIndex,
  1608. IN ULONG InstanceIndex,
  1609. IN ULONG BufferSize,
  1610. IN PUCHAR Buffer
  1611. )
  1612. /*++
  1613. Routine Description:
  1614. This routine is a callback into the driver to set the contents of
  1615. a data block. When the driver has finished filling the data block it
  1616. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1617. return STATUS_PENDING if the irp cannot be completed immediately.
  1618. Arguments:
  1619. DeviceObject is the device whose data block is being queried
  1620. Irp is the Irp that makes this request
  1621. GuidIndex is the index into the list of guids provided when the
  1622. device registered
  1623. InstanceIndex is the index that denotes which instance of the data block
  1624. is being queried.
  1625. BufferSize has the size of the data block passed
  1626. Buffer has the new values for the data block
  1627. Return Value:
  1628. status
  1629. --*/
  1630. {
  1631. PDEVICE_EXTENSION_FDO deviceExtensionFdo;
  1632. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  1633. NTSTATUS status;
  1634. ULONG size = 0;
  1635. BOOLEAN bEnableSS, bSelectiveSuspendEnabled = FALSE, globaDisableSS;
  1636. deviceExtensionFdo = (PDEVICE_EXTENSION_FDO) DeviceObject->DeviceExtension;
  1637. deviceExtensionHub = (PDEVICE_EXTENSION_HUB) DeviceObject->DeviceExtension;
  1638. switch(GuidIndex) {
  1639. case WMI_USB_DRIVER_INFORMATION:
  1640. status = /*STATUS_WMI_READ_ONLY*/STATUS_INVALID_DEVICE_REQUEST;
  1641. break;
  1642. case WMI_USB_POWER_DEVICE_ENABLE:
  1643. // We only support this for the Root Hub but this WMI request should
  1644. // only occur for the Root Hub because we only register this GUID
  1645. // for the Root Hub. We perform a sanity check anyway.
  1646. USBH_ASSERT(deviceExtensionFdo->ExtensionType == EXTENSION_TYPE_HUB);
  1647. USBH_ASSERT(IS_ROOT_HUB(deviceExtensionHub));
  1648. USBH_RegQueryUSBGlobalSelectiveSuspend(&globaDisableSS);
  1649. if (deviceExtensionFdo->ExtensionType == EXTENSION_TYPE_HUB &&
  1650. IS_ROOT_HUB(deviceExtensionHub) &&
  1651. !globaDisableSS) {
  1652. size = sizeof(BOOLEAN);
  1653. if (BufferSize < size) {
  1654. status = STATUS_BUFFER_TOO_SMALL;
  1655. } else if (0 != InstanceIndex) {
  1656. status = STATUS_INVALID_DEVICE_REQUEST;
  1657. } else {
  1658. bEnableSS = *(PBOOLEAN)Buffer;
  1659. status = USBD_QuerySelectiveSuspendEnabled(deviceExtensionHub,
  1660. &bSelectiveSuspendEnabled);
  1661. if (NT_SUCCESS(status) &&
  1662. bEnableSS != bSelectiveSuspendEnabled) {
  1663. // Update global flag and registry with new setting.
  1664. status = USBD_SetSelectiveSuspendEnabled(deviceExtensionHub,
  1665. bEnableSS);
  1666. if (NT_SUCCESS(status)) {
  1667. if (bEnableSS) {
  1668. // We are being asked to enable Selective Suspend
  1669. // when it was previously disabled.
  1670. // Find the end hubs in the chain and idle them
  1671. // out if ready. This will trickle down to
  1672. // the parent hubs if all hubs are idle.
  1673. USBH_CheckLeafHubsIdle(deviceExtensionHub);
  1674. status = STATUS_SUCCESS;
  1675. } else {
  1676. // We are being asked to disable Selective Suspend
  1677. // when it was previously enabled.
  1678. if (deviceExtensionHub->CurrentPowerState != PowerDeviceD0 &&
  1679. (deviceExtensionHub->HubFlags & HUBFLAG_NEED_CLEANUP)) {
  1680. USBH_HubSetD0(deviceExtensionHub);
  1681. } else {
  1682. USBH_HubCompletePortIdleIrps(deviceExtensionHub,
  1683. STATUS_CANCELLED);
  1684. }
  1685. status = STATUS_SUCCESS;
  1686. }
  1687. }
  1688. }
  1689. }
  1690. } else {
  1691. status = STATUS_INVALID_DEVICE_REQUEST;
  1692. }
  1693. break;
  1694. default:
  1695. status = STATUS_WMI_GUID_NOT_FOUND;
  1696. }
  1697. status = WmiCompleteRequest(DeviceObject,
  1698. Irp,
  1699. status,
  1700. 0,
  1701. IO_NO_INCREMENT);
  1702. return(status);
  1703. }
  1704. NTSTATUS
  1705. USBH_QueryWmiDataBlock(
  1706. IN PDEVICE_OBJECT DeviceObject,
  1707. IN PIRP Irp,
  1708. IN ULONG GuidIndex,
  1709. IN ULONG InstanceIndex,
  1710. IN ULONG InstanceCount,
  1711. IN OUT PULONG InstanceLengthArray,
  1712. IN ULONG OutBufferSize,
  1713. OUT PUCHAR Buffer
  1714. )
  1715. /*++
  1716. Routine Description:
  1717. This routine is a callback into the driver to query for the contents of
  1718. a data block. When the driver has finished filling the data block it
  1719. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1720. return STATUS_PENDING if the irp cannot be completed immediately.
  1721. Arguments:
  1722. DeviceObject is the device whose data block is being queried
  1723. Irp is the Irp that makes this request
  1724. GuidIndex is the index into the list of guids provided when the
  1725. device registered
  1726. InstanceIndex is the index that denotes which instance of the data block
  1727. is being queried.
  1728. InstanceCount is the number of instnaces expected to be returned for
  1729. the data block.
  1730. InstanceLengthArray is a pointer to an array of ULONG that returns the
  1731. lengths of each instance of the data block. If this is NULL then
  1732. there was not enough space in the output buffer to fufill the request
  1733. so the irp should be completed with the buffer needed.
  1734. BufferAvail on has the maximum size available to write the data
  1735. block.
  1736. Buffer on return is filled with the returned data block
  1737. Return Value:
  1738. status
  1739. --*/
  1740. {
  1741. PDEVICE_EXTENSION_FDO deviceExtensionFdo;
  1742. PUSB_NOTIFICATION notification;
  1743. NTSTATUS status;
  1744. ULONG size = 0;
  1745. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  1746. BOOLEAN bSelectiveSuspendEnabled = FALSE,globaDisableSS;
  1747. deviceExtensionFdo = (PDEVICE_EXTENSION_FDO) DeviceObject->DeviceExtension;
  1748. deviceExtensionHub = (PDEVICE_EXTENSION_HUB) DeviceObject->DeviceExtension;
  1749. notification = (PUSB_NOTIFICATION) Buffer;
  1750. USBH_KdPrint((1,"'WMI Query Data Block on hub ext %x\n",
  1751. deviceExtensionHub));
  1752. switch (GuidIndex) {
  1753. case WMI_USB_DRIVER_INFORMATION:
  1754. if (InstanceLengthArray != NULL) {
  1755. *InstanceLengthArray = 0;
  1756. status = STATUS_SUCCESS;
  1757. } else {
  1758. status = STATUS_BUFFER_TOO_SMALL;
  1759. }
  1760. break;
  1761. case WMI_USB_POWER_DEVICE_ENABLE:
  1762. // We only support this for the Root Hub but this WMI request should
  1763. // only occur for the Root Hub because we only register this GUID
  1764. // for the Root Hub. We perform a sanity check anyway.
  1765. USBH_ASSERT(deviceExtensionFdo->ExtensionType == EXTENSION_TYPE_HUB);
  1766. USBH_ASSERT(IS_ROOT_HUB(deviceExtensionHub));
  1767. USBH_RegQueryUSBGlobalSelectiveSuspend(&globaDisableSS);
  1768. if (deviceExtensionFdo->ExtensionType == EXTENSION_TYPE_HUB &&
  1769. IS_ROOT_HUB(deviceExtensionHub) &&
  1770. !globaDisableSS) {
  1771. //
  1772. // Only registers 1 instance for this GUID.
  1773. //
  1774. if ((0 != InstanceIndex) || (1 != InstanceCount)) {
  1775. status = STATUS_INVALID_DEVICE_REQUEST;
  1776. break;
  1777. }
  1778. size = sizeof(BOOLEAN);
  1779. if (OutBufferSize < size) {
  1780. status = STATUS_BUFFER_TOO_SMALL;
  1781. break;
  1782. }
  1783. status = USBD_QuerySelectiveSuspendEnabled(deviceExtensionHub,
  1784. &bSelectiveSuspendEnabled);
  1785. if (!NT_SUCCESS(status)) {
  1786. break;
  1787. }
  1788. *(PBOOLEAN)Buffer = bSelectiveSuspendEnabled;
  1789. *InstanceLengthArray = size;
  1790. status = STATUS_SUCCESS;
  1791. } else {
  1792. status = STATUS_INVALID_DEVICE_REQUEST;
  1793. }
  1794. break;
  1795. default:
  1796. status = STATUS_WMI_GUID_NOT_FOUND;
  1797. }
  1798. status = WmiCompleteRequest(DeviceObject,
  1799. Irp,
  1800. status,
  1801. size,
  1802. IO_NO_INCREMENT);
  1803. return status;
  1804. }
  1805. NTSTATUS
  1806. USBH_PortQueryWmiDataBlock(
  1807. IN PDEVICE_OBJECT DeviceObject,
  1808. IN PIRP Irp,
  1809. IN ULONG GuidIndex,
  1810. IN ULONG InstanceIndex,
  1811. IN ULONG InstanceCount,
  1812. IN OUT PULONG InstanceLengthArray,
  1813. IN ULONG OutBufferSize,
  1814. OUT PUCHAR Buffer
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. This routine is a callback into the driver to query for the contents of
  1819. a data block. When the driver has finished filling the data block it
  1820. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1821. return STATUS_PENDING if the irp cannot be completed immediately.
  1822. Arguments:
  1823. DeviceObject is the device whose data block is being queried
  1824. Irp is the Irp that makes this request
  1825. GuidIndex is the index into the list of guids provided when the
  1826. device registered
  1827. InstanceIndex is the index that denotes which instance of the data block
  1828. is being queried.
  1829. InstanceCount is the number of instnaces expected to be returned for
  1830. the data block.
  1831. InstanceLengthArray is a pointer to an array of ULONG that returns the
  1832. lengths of each instance of the data block. If this is NULL then
  1833. there was not enough space in the output buffer to fufill the request
  1834. so the irp should be completed with the buffer needed.
  1835. BufferAvail on has the maximum size available to write the data
  1836. block.
  1837. Buffer on return is filled with the returned data block
  1838. Return Value:
  1839. status
  1840. --*/
  1841. {
  1842. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  1843. PUSB_DEVICE_UI_FIRMWARE_REVISION fwRevBuf;
  1844. NTSTATUS status;
  1845. ULONG size = 0;
  1846. PWCHAR revstr;
  1847. USHORT bcdDevice;
  1848. USHORT stringsize;
  1849. deviceExtensionPort = (PDEVICE_EXTENSION_PORT) DeviceObject->DeviceExtension;
  1850. USBH_KdPrint((1,"'WMI Query Data Block on PORT PDO ext %x\n",
  1851. deviceExtensionPort));
  1852. switch (GuidIndex) {
  1853. case 0:
  1854. // Return USB device FW revision # in the following format "xx.xx".
  1855. // Need buffer large enough for this string plus NULL terminator.
  1856. stringsize = 6 * sizeof(WCHAR);
  1857. size = sizeof(USB_DEVICE_UI_FIRMWARE_REVISION) + (ULONG)stringsize;
  1858. if (OutBufferSize < size) {
  1859. status = STATUS_BUFFER_TOO_SMALL;
  1860. break;
  1861. }
  1862. bcdDevice = deviceExtensionPort->DeviceDescriptor.bcdDevice;
  1863. fwRevBuf = (PUSB_DEVICE_UI_FIRMWARE_REVISION)Buffer;
  1864. revstr = &fwRevBuf->FirmwareRevisionString[0];
  1865. *revstr = BcdNibbleToAscii(bcdDevice >> 12);
  1866. *(revstr+1) = BcdNibbleToAscii((bcdDevice >> 8) & 0x000f);
  1867. *(revstr+2) = '.';
  1868. *(revstr+3) = BcdNibbleToAscii((bcdDevice >> 4) & 0x000f);
  1869. *(revstr+4) = BcdNibbleToAscii(bcdDevice & 0x000f);
  1870. *(revstr+5) = 0;
  1871. fwRevBuf->Length = stringsize;
  1872. *InstanceLengthArray = size;
  1873. status = STATUS_SUCCESS;
  1874. USBH_KdPrint((1,"'WMI Query Data Block, returning FW rev # '%ws'\n",
  1875. revstr));
  1876. break;
  1877. default:
  1878. status = STATUS_WMI_GUID_NOT_FOUND;
  1879. }
  1880. status = WmiCompleteRequest(DeviceObject,
  1881. Irp,
  1882. status,
  1883. size,
  1884. IO_NO_INCREMENT);
  1885. return status;
  1886. }
  1887. NTSTATUS
  1888. USBH_ExecuteWmiMethod(
  1889. IN PDEVICE_OBJECT DeviceObject,
  1890. IN PIRP Irp,
  1891. IN ULONG GuidIndex,
  1892. IN ULONG InstanceIndex,
  1893. IN ULONG MethodId,
  1894. IN ULONG InBufferSize,
  1895. IN ULONG OutBufferSize,
  1896. IN OUT PUCHAR Buffer
  1897. )
  1898. /*++
  1899. Routine Description:
  1900. This routine is a callback into the driver to execute a method. When the
  1901. driver has finished filling the data block it must call
  1902. WmiCompleteRequest to complete the irp. The driver can
  1903. return STATUS_PENDING if the irp cannot be completed immediately.
  1904. Arguments:
  1905. DeviceObject is the device whose data block is being queried
  1906. Irp is the Irp that makes this request
  1907. GuidIndex is the index into the list of guids provided when the
  1908. device registered
  1909. InstanceIndex is the index that denotes which instance of the data block
  1910. is being called.
  1911. MethodId has the id of the method being called
  1912. InBufferSize has the size of the data block passed in as the input to
  1913. the method.
  1914. OutBufferSize on entry has the maximum size available to write the
  1915. returned data block.
  1916. Buffer on entry has the input data block and on return has the output
  1917. output data block.
  1918. Return Value:
  1919. status
  1920. --*/
  1921. {
  1922. PDEVICE_EXTENSION_FDO deviceExtensionFdo;
  1923. PUSB_NOTIFICATION notification;
  1924. NTSTATUS ntStatus = STATUS_WMI_GUID_NOT_FOUND;
  1925. ULONG size = 0;
  1926. PDEVICE_EXTENSION_HUB deviceExtensionHub;
  1927. PDEVICE_EXTENSION_PORT portPdoExt;
  1928. BOOLEAN bDoCheckHubIdle = FALSE;
  1929. deviceExtensionFdo = (PDEVICE_EXTENSION_FDO) DeviceObject->DeviceExtension;
  1930. if (deviceExtensionFdo->ExtensionType == EXTENSION_TYPE_PARENT) {
  1931. // Looks like a child PDO of a composite device is causing the problem.
  1932. // Let's be sure to get the correct device extension for the hub.
  1933. portPdoExt = deviceExtensionFdo->PhysicalDeviceObject->DeviceExtension;
  1934. deviceExtensionHub = portPdoExt->DeviceExtensionHub;
  1935. } else {
  1936. deviceExtensionHub = (PDEVICE_EXTENSION_HUB) DeviceObject->DeviceExtension;
  1937. }
  1938. USBH_ASSERT(EXTENSION_TYPE_HUB == deviceExtensionHub->ExtensionType);
  1939. // If this hub is currently Selective Suspended, then we need to
  1940. // power up the hub first before sending any requests along to it.
  1941. // Make sure hub has been started, though.
  1942. if (deviceExtensionHub->CurrentPowerState != PowerDeviceD0 &&
  1943. (deviceExtensionHub->HubFlags & HUBFLAG_NEED_CLEANUP)) {
  1944. bDoCheckHubIdle = TRUE;
  1945. USBH_HubSetD0(deviceExtensionHub);
  1946. }
  1947. notification = (PUSB_NOTIFICATION) Buffer;
  1948. USBH_KdPrint((1,"'WMI Execute Method on hub ext %x\n",
  1949. deviceExtensionHub));
  1950. switch (GuidIndex) {
  1951. case WMI_USB_DRIVER_INFORMATION:
  1952. size = sizeof(*notification);
  1953. if (OutBufferSize < size) {
  1954. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1955. break;
  1956. }
  1957. // switch(MethodId) {
  1958. switch (notification->NotificationType) {
  1959. case EnumerationFailure:
  1960. {
  1961. PUSB_CONNECTION_NOTIFICATION connectionNotification;
  1962. USBH_KdPrint((1,"'Method EnumerationFailure %x\n"));
  1963. connectionNotification = (PUSB_CONNECTION_NOTIFICATION) Buffer;
  1964. size = sizeof(*connectionNotification);
  1965. if (OutBufferSize < size) {
  1966. USBH_KdPrint((1,"'pwr - buff too small\n"));
  1967. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1968. } else {
  1969. portPdoExt =
  1970. USBH_GetPortPdoExtension(deviceExtensionHub,
  1971. connectionNotification->ConnectionNumber);
  1972. if (portPdoExt) {
  1973. connectionNotification->EnumerationFailReason =
  1974. portPdoExt->FailReasonId;
  1975. ntStatus = STATUS_SUCCESS;
  1976. } else {
  1977. USBH_KdPrint((1,"'ef - bad connection index\n"));
  1978. ntStatus = STATUS_INVALID_PARAMETER;
  1979. }
  1980. }
  1981. }
  1982. break;
  1983. case InsufficentBandwidth:
  1984. {
  1985. PUSB_CONNECTION_NOTIFICATION connectionNotification;
  1986. USBH_KdPrint((1,"'Method InsufficentBandwidth\n"));
  1987. connectionNotification = (PUSB_CONNECTION_NOTIFICATION) Buffer;
  1988. size = sizeof(*connectionNotification);
  1989. if (OutBufferSize < size) {
  1990. USBH_KdPrint((1,"'pwr - buff too small\n"));
  1991. ntStatus = STATUS_BUFFER_TOO_SMALL;
  1992. } else {
  1993. portPdoExt =
  1994. USBH_GetPortPdoExtension(deviceExtensionHub,
  1995. connectionNotification->ConnectionNumber);
  1996. if (portPdoExt) {
  1997. connectionNotification->RequestedBandwidth =
  1998. portPdoExt->RequestedBandwidth;
  1999. ntStatus = STATUS_SUCCESS;
  2000. } else {
  2001. USBH_KdPrint((1,"'bw - bad connection index\n"));
  2002. ntStatus = STATUS_INVALID_PARAMETER;
  2003. }
  2004. }
  2005. }
  2006. break;
  2007. case OverCurrent:
  2008. // nothing to do here
  2009. USBH_KdPrint((1,"'Method OverCurrent\n"));
  2010. ntStatus = STATUS_SUCCESS;
  2011. size = 0;
  2012. break;
  2013. case InsufficentPower:
  2014. {
  2015. PUSB_CONNECTION_NOTIFICATION connectionNotification;
  2016. USBH_KdPrint((1,"'Method InsufficentPower\n"));
  2017. size = sizeof(*connectionNotification);
  2018. if (OutBufferSize < size) {
  2019. USBH_KdPrint((1,"'pwr - buff too small\n"));
  2020. ntStatus = STATUS_BUFFER_TOO_SMALL;
  2021. } else {
  2022. connectionNotification = (PUSB_CONNECTION_NOTIFICATION) Buffer;
  2023. USBH_KdPrint((1,"'pwr - connection %d\n",
  2024. connectionNotification->ConnectionNumber));
  2025. if (connectionNotification->ConnectionNumber) {
  2026. if (portPdoExt = USBH_GetPortPdoExtension(deviceExtensionHub,
  2027. connectionNotification->ConnectionNumber)) {
  2028. connectionNotification->PowerRequested =
  2029. portPdoExt->PowerRequested;
  2030. ntStatus = STATUS_SUCCESS;
  2031. }
  2032. } else {
  2033. USBH_KdPrint((1,"'pwr - bad connection index\n"));
  2034. ntStatus = STATUS_INVALID_PARAMETER;
  2035. }
  2036. }
  2037. }
  2038. break;
  2039. case ResetOvercurrent:
  2040. {
  2041. PUSB_CONNECTION_NOTIFICATION connectionNotification;
  2042. USBH_KdPrint((1,"'Method ResetOvercurrent\n"));
  2043. size = sizeof(*connectionNotification);
  2044. if (OutBufferSize < size) {
  2045. USBH_KdPrint((1,"'reset - buff too small\n"));
  2046. ntStatus = STATUS_BUFFER_TOO_SMALL;
  2047. } else {
  2048. connectionNotification = (PUSB_CONNECTION_NOTIFICATION) Buffer;
  2049. if (connectionNotification->ConnectionNumber) {
  2050. USBH_KdPrint((1,"'reset - port %d\n", connectionNotification->ConnectionNumber));
  2051. portPdoExt = USBH_GetPortPdoExtension(deviceExtensionHub,
  2052. connectionNotification->ConnectionNumber);
  2053. ntStatus = USBH_ResetPortOvercurrent(deviceExtensionHub,
  2054. (USHORT)connectionNotification->ConnectionNumber,
  2055. portPdoExt);
  2056. // } else {
  2057. // // bad connection index
  2058. // USBH_KdPrint((1,"'reset - bad connection index\n"));
  2059. // ntStatus = STATUS_INVALID_PARAMETER;
  2060. // }
  2061. } else {
  2062. // this is a reset for the whole hub
  2063. USBH_KdPrint((1,"'not implemented yet\n"));
  2064. TEST_TRAP();
  2065. ntStatus = STATUS_NOT_IMPLEMENTED;
  2066. }
  2067. }
  2068. }
  2069. break;
  2070. case AcquireBusInfo:
  2071. {
  2072. PUSB_BUS_NOTIFICATION busNotification;
  2073. USBH_KdPrint((1,"'Method AcquireBusInfo\n"));
  2074. size = sizeof(*busNotification);
  2075. if (OutBufferSize < size) {
  2076. USBH_KdPrint((1,"'AcquireBusInfo - buff too small\n"));
  2077. ntStatus = STATUS_BUFFER_TOO_SMALL;
  2078. } else {
  2079. busNotification = (PUSB_BUS_NOTIFICATION) Buffer;
  2080. // ntStatus = USBH_SyncGetControllerInfo(
  2081. // deviceExtensionHub->TopOfStackDeviceObject,
  2082. // busNotification,
  2083. // sizeof(*busNotification),
  2084. // IOCTL_INTERNAL_USB_GET_BUS_INFO);
  2085. ntStatus = USBHUB_GetBusInfo(deviceExtensionHub,
  2086. busNotification,
  2087. NULL);
  2088. USBH_KdPrint((1,"'Notification, controller name length = %d\n",
  2089. busNotification->ControllerNameLength));
  2090. }
  2091. }
  2092. break;
  2093. case AcquireHubName:
  2094. {
  2095. PUSB_HUB_NAME hubName;
  2096. PUSB_ACQUIRE_INFO acquireInfo;
  2097. USBH_KdPrint((1,"'Method AcquireHubName\n"));
  2098. size = sizeof(USB_ACQUIRE_INFO);
  2099. acquireInfo = (PUSB_ACQUIRE_INFO) Buffer;
  2100. if (OutBufferSize < size) {
  2101. ntStatus = STATUS_BUFFER_TOO_SMALL;
  2102. break;
  2103. }
  2104. size = acquireInfo->TotalSize;
  2105. hubName = (PUSB_HUB_NAME) &acquireInfo->TotalSize;
  2106. // TotalSize contains the size of the notification type as well
  2107. hubName->ActualLength -= sizeof(USB_NOTIFICATION_TYPE);
  2108. if (IS_ROOT_HUB(deviceExtensionHub)) {
  2109. hubName->ActualLength -= sizeof(hubName->ActualLength);
  2110. ntStatus = USBHUB_GetRootHubName(deviceExtensionHub,
  2111. hubName->HubName,
  2112. &hubName->ActualLength);
  2113. // hubName->ActualLength += sizeof(hubName->ActualLength);
  2114. } else {
  2115. ntStatus = USBH_SyncGetHubName(
  2116. deviceExtensionHub->TopOfStackDeviceObject,
  2117. hubName,
  2118. hubName->ActualLength);
  2119. }
  2120. // readjust to previous value
  2121. hubName->ActualLength += sizeof(USB_NOTIFICATION_TYPE);
  2122. }
  2123. break;
  2124. case AcquireControllerName:
  2125. {
  2126. PUSB_HUB_NAME controllerName;
  2127. PUSB_ACQUIRE_INFO acquireInfo;
  2128. USBH_KdPrint((1,"'Method AcquireControllerName\n"));
  2129. size = sizeof(USB_ACQUIRE_INFO);
  2130. acquireInfo = (PUSB_ACQUIRE_INFO) Buffer;
  2131. if (OutBufferSize < size) {
  2132. ntStatus = STATUS_BUFFER_TOO_SMALL;
  2133. break;
  2134. }
  2135. USBH_KdPrint((1,"'TotalSize %d\n", acquireInfo->TotalSize));
  2136. USBH_KdPrint((1,"'NotificationType %x\n", acquireInfo->NotificationType));
  2137. size = acquireInfo->TotalSize;
  2138. controllerName = (PUSB_HUB_NAME) &acquireInfo->TotalSize;
  2139. // TotalSize contains the size of the notification type as well
  2140. controllerName->ActualLength -= sizeof(USB_NOTIFICATION_TYPE);
  2141. // ntStatus = USBH_SyncGetControllerInfo(deviceExtensionHub->TopOfStackDeviceObject,
  2142. // controllerName,
  2143. // controllerName->ActualLength,
  2144. // IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME);
  2145. ntStatus = USBHUB_GetControllerName(deviceExtensionHub,
  2146. controllerName,
  2147. controllerName->ActualLength);
  2148. // readjust to previous value
  2149. controllerName->ActualLength += sizeof(USB_NOTIFICATION_TYPE);
  2150. USBH_KdPrint((1,"'Method AcquireControllerName %x - %d\n",
  2151. acquireInfo, controllerName->ActualLength));
  2152. }
  2153. break;
  2154. case HubOvercurrent:
  2155. USBH_KdPrint((1,"'Method HubOvercurrent\n"));
  2156. USBH_KdPrint((1,"'not implemented yet\n"));
  2157. ntStatus = STATUS_SUCCESS;
  2158. size = 0;
  2159. break;
  2160. case HubPowerChange:
  2161. USBH_KdPrint((1,"'Method HubPowerChange\n"));
  2162. USBH_KdPrint((1,"'not implemented yet\n"));
  2163. ntStatus = STATUS_SUCCESS;
  2164. size = 0;
  2165. break;
  2166. case HubNestedTooDeeply:
  2167. // nothing to do here
  2168. USBH_KdPrint((1,"'Method HubNestedTooDeeply\n"));
  2169. ntStatus = STATUS_SUCCESS;
  2170. size = 0;
  2171. break;
  2172. case ModernDeviceInLegacyHub:
  2173. // nothing to do here
  2174. USBH_KdPrint((1,"'Method ModernDeviceInLegacyHub\n"));
  2175. ntStatus = STATUS_SUCCESS;
  2176. size = 0;
  2177. break;
  2178. }
  2179. break;
  2180. default:
  2181. ntStatus = STATUS_WMI_GUID_NOT_FOUND;
  2182. }
  2183. ntStatus = WmiCompleteRequest(DeviceObject,
  2184. Irp,
  2185. ntStatus,
  2186. size,
  2187. IO_NO_INCREMENT);
  2188. if (bDoCheckHubIdle) {
  2189. USBH_CheckHubIdle(deviceExtensionHub);
  2190. }
  2191. return ntStatus;
  2192. }
  2193. NTSTATUS
  2194. USBH_QueryWmiRegInfo(
  2195. IN PDEVICE_OBJECT DeviceObject,
  2196. OUT PULONG RegFlags,
  2197. OUT PUNICODE_STRING InstanceName,
  2198. OUT PUNICODE_STRING *RegistryPath,
  2199. OUT PUNICODE_STRING MofResourceName,
  2200. OUT PDEVICE_OBJECT *Pdo
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. This routine is a callback into the driver to retrieve information about
  2205. the guids being registered.
  2206. Implementations of this routine may be in paged memory
  2207. Arguments:
  2208. DeviceObject is the device whose registration information is needed
  2209. *RegFlags returns with a set of flags that describe all of the guids being
  2210. registered for this device. If the device wants enable and disable
  2211. collection callbacks before receiving queries for the registered
  2212. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  2213. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  2214. the instance name is determined from the PDO associated with the
  2215. device object. Note that the PDO must have an associated devnode. If
  2216. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  2217. name for the device. These flags are ORed into the flags specified
  2218. by the GUIDREGINFO for each guid.
  2219. InstanceName returns with the instance name for the guids if
  2220. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  2221. caller will call ExFreePool with the buffer returned.
  2222. *RegistryPath returns with the registry path of the driver. This is
  2223. required
  2224. MofResourceName returns with the name of the MOF resource attached to
  2225. the binary file. If the driver does not have a mof resource attached
  2226. then this can be returned unmodified. If a value is returned then
  2227. it is NOT freed.
  2228. *Pdo returns with the device object for the PDO associated with this
  2229. device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
  2230. *RegFlags.
  2231. Return Value:
  2232. status
  2233. --*/
  2234. {
  2235. PDEVICE_EXTENSION_HUB deviceExtensionHub; // pointer to our device
  2236. // extension
  2237. deviceExtensionHub = (PDEVICE_EXTENSION_HUB) DeviceObject->DeviceExtension;
  2238. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  2239. *RegistryPath = &UsbhRegistryPath;
  2240. *Pdo = deviceExtensionHub->PhysicalDeviceObject;
  2241. return STATUS_SUCCESS;
  2242. }
  2243. NTSTATUS
  2244. USBH_PortQueryWmiRegInfo(
  2245. IN PDEVICE_OBJECT DeviceObject,
  2246. OUT PULONG RegFlags,
  2247. OUT PUNICODE_STRING InstanceName,
  2248. OUT PUNICODE_STRING *RegistryPath,
  2249. OUT PUNICODE_STRING MofResourceName,
  2250. OUT PDEVICE_OBJECT *Pdo
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. This routine is a callback into the driver to retrieve information about
  2255. the guids being registered.
  2256. Implementations of this routine may be in paged memory
  2257. Arguments:
  2258. DeviceObject is the device whose registration information is needed
  2259. *RegFlags returns with a set of flags that describe all of the guids being
  2260. registered for this device. If the device wants enable and disable
  2261. collection callbacks before receiving queries for the registered
  2262. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  2263. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  2264. the instance name is determined from the PDO associated with the
  2265. device object. Note that the PDO must have an associated devnode. If
  2266. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  2267. name for the device. These flags are ORed into the flags specified
  2268. by the GUIDREGINFO for each guid.
  2269. InstanceName returns with the instance name for the guids if
  2270. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  2271. caller will call ExFreePool with the buffer returned.
  2272. *RegistryPath returns with the registry path of the driver. This is
  2273. required
  2274. MofResourceName returns with the name of the MOF resource attached to
  2275. the binary file. If the driver does not have a mof resource attached
  2276. then this can be returned unmodified. If a value is returned then
  2277. it is NOT freed.
  2278. *Pdo returns with the device object for the PDO associated with this
  2279. device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
  2280. *RegFlags.
  2281. Return Value:
  2282. status
  2283. --*/
  2284. {
  2285. PDEVICE_EXTENSION_PORT deviceExtensionPort;
  2286. deviceExtensionPort = (PDEVICE_EXTENSION_PORT) DeviceObject->DeviceExtension;
  2287. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  2288. *RegistryPath = &UsbhRegistryPath;
  2289. *Pdo = deviceExtensionPort->PortPhysicalDeviceObject;
  2290. return STATUS_SUCCESS;
  2291. }
  2292. #endif /* WMI_SUPPORT */
  2293. NTSTATUS
  2294. USBH_ResetPortOvercurrent(
  2295. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  2296. IN USHORT PortNumber,
  2297. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort
  2298. )
  2299. /*
  2300. * Description:
  2301. *
  2302. * Reset the overcurrent condition for a port
  2303. *
  2304. * Arguments:
  2305. *
  2306. * Return:
  2307. *
  2308. * NTSTATUS
  2309. *
  2310. * -- */
  2311. {
  2312. NTSTATUS ntStatus = STATUS_SUCCESS, status;
  2313. PORT_STATE portState;
  2314. PPORT_DATA portData;
  2315. USBH_KdPrint((0,"'Reset Overcurrent for port %d\n", PortNumber));
  2316. // we will need to re-enable and re-power the port
  2317. ntStatus = USBH_SyncGetPortStatus(DeviceExtensionHub,
  2318. PortNumber,
  2319. (PUCHAR) &portState,
  2320. sizeof(portState));
  2321. //
  2322. // port should be powered off at this point
  2323. //
  2324. LOGENTRY(LOG_PNP, "WMIo", DeviceExtensionHub,
  2325. portState.PortStatus,
  2326. portState.PortChange);
  2327. if (portState.PortStatus & PORT_STATUS_POWER) {
  2328. ntStatus = STATUS_INVALID_PARAMETER;
  2329. } else {
  2330. if (NT_SUCCESS(ntStatus) && DeviceExtensionPort) {
  2331. // clear overcurrent Flags
  2332. DeviceExtensionPort->PortPdoFlags &=
  2333. ~PORTPDO_OVERCURRENT;
  2334. }
  2335. // power up the port
  2336. ntStatus = USBH_SyncPowerOnPort(DeviceExtensionHub,
  2337. PortNumber,
  2338. TRUE);
  2339. USBH_InternalCyclePort(DeviceExtensionHub, PortNumber, DeviceExtensionPort);
  2340. }
  2341. return ntStatus;
  2342. }
  2343. NTSTATUS
  2344. USBH_CalculateInterfaceBandwidth(
  2345. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  2346. IN PUSBD_INTERFACE_INFORMATION Interface,
  2347. IN OUT PULONG Bandwidth // in kenr units?
  2348. )
  2349. /*
  2350. * Description:
  2351. *
  2352. * Arguments:
  2353. *
  2354. * Return:
  2355. *
  2356. * NTSTATUS
  2357. *
  2358. * -- */
  2359. {
  2360. NTSTATUS ntStatus = STATUS_SUCCESS;
  2361. ULONG i, bw;
  2362. // we'll need to walk through the interface
  2363. // and figure out how much BW it requires
  2364. for (i=0; i<Interface->NumberOfPipes; i++) {
  2365. //#ifdef USB2
  2366. // bw = USBD_CalculateUsbBandwidthEx(
  2367. // (ULONG) Interface->Pipes[i].MaximumPacketSize,
  2368. // (UCHAR) Interface->Pipes[i].PipeType,
  2369. // (BOOLEAN) (DeviceExtensionPort->PortPdoFlags &
  2370. // PORTPDO_LOW_SPEED_DEVICE));
  2371. //#else
  2372. bw = USBD_CalculateUsbBandwidth(
  2373. (ULONG) Interface->Pipes[i].MaximumPacketSize,
  2374. (UCHAR) Interface->Pipes[i].PipeType,
  2375. (BOOLEAN) (DeviceExtensionPort->PortPdoFlags &
  2376. PORTPDO_LOW_SPEED_DEVICE));
  2377. //#endif
  2378. USBH_KdPrint((1,"'ept = %d packetsize = %d bw = %d\n",
  2379. Interface->Pipes[i].PipeType,
  2380. Interface->Pipes[i].MaximumPacketSize, bw));
  2381. *Bandwidth += bw;
  2382. }
  2383. return ntStatus;
  2384. }