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

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