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.

1415 lines
34 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. busif.c
  5. Abstract:
  6. Links to new usb 2.0 stack
  7. The effect is that when running on the USB2 stack the hub
  8. is no longer depenent on the port driver archetecture or
  9. USBD for the PnP services:
  10. CreateDevice
  11. InitailiazeDevice
  12. RemoveDevice
  13. Environment:
  14. kernel mode only
  15. Notes:
  16. Revision History:
  17. 10-29-95 : created
  18. --*/
  19. #include <wdm.h>
  20. #ifdef WMI_SUPPORT
  21. #include <wmilib.h>
  22. #endif /* WMI_SUPPORT */
  23. #include "usbhub.h"
  24. #ifdef USB2
  25. NTSTATUS
  26. USBD_DeferIrpCompletion(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp,
  29. IN PVOID Context
  30. )
  31. /*++
  32. Routine Description:
  33. This routine is called when the port driver completes an IRP.
  34. Arguments:
  35. DeviceObject - Pointer to the device object for the class device.
  36. Irp - Irp completed.
  37. Context - Driver defined context.
  38. Return Value:
  39. The function value is the final status from the operation.
  40. --*/
  41. {
  42. PKEVENT event = Context;
  43. KeSetEvent(event,
  44. 1,
  45. FALSE);
  46. return STATUS_MORE_PROCESSING_REQUIRED;
  47. }
  48. NTSTATUS
  49. USBHUB_GetBusInterface(
  50. IN PDEVICE_OBJECT RootHubPdo,
  51. IN PUSB_HUB_BUS_INTERFACE BusInterface
  52. )
  53. /*++
  54. Routine Description:
  55. Arguments:
  56. Return Value:
  57. returns success if USB2 stack
  58. --*/
  59. {
  60. PIO_STACK_LOCATION nextStack;
  61. PIRP irp;
  62. NTSTATUS ntStatus;
  63. KEVENT event;
  64. irp = IoAllocateIrp(RootHubPdo->StackSize, FALSE);
  65. if (!irp) {
  66. return STATUS_UNSUCCESSFUL;
  67. }
  68. // All PnP IRP's need the Status field initialized to STATUS_NOT_SUPPORTED.
  69. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  70. KeInitializeEvent(&event, NotificationEvent, FALSE);
  71. IoSetCompletionRoutine(irp,
  72. USBD_DeferIrpCompletion,
  73. &event,
  74. TRUE,
  75. TRUE,
  76. TRUE);
  77. nextStack = IoGetNextIrpStackLocation(irp);
  78. ASSERT(nextStack != NULL);
  79. nextStack->MajorFunction= IRP_MJ_PNP;
  80. nextStack->MinorFunction= IRP_MN_QUERY_INTERFACE;
  81. // init busif
  82. //busIf->
  83. nextStack->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;
  84. nextStack->Parameters.QueryInterface.InterfaceSpecificData =
  85. RootHubPdo;
  86. nextStack->Parameters.QueryInterface.InterfaceType =
  87. &USB_BUS_INTERFACE_HUB_GUID;
  88. nextStack->Parameters.QueryInterface.Size =
  89. sizeof(*BusInterface);
  90. nextStack->Parameters.QueryInterface.Version =
  91. HUB_BUSIF_VERSION;
  92. ntStatus = IoCallDriver(RootHubPdo,
  93. irp);
  94. if (ntStatus == STATUS_PENDING) {
  95. KeWaitForSingleObject(
  96. &event,
  97. Suspended,
  98. KernelMode,
  99. FALSE,
  100. NULL);
  101. ntStatus = irp->IoStatus.Status;
  102. }
  103. if (NT_SUCCESS(ntStatus)) {
  104. // we have a bus interface
  105. ASSERT(BusInterface->Version == HUB_BUSIF_VERSION);
  106. ASSERT(BusInterface->Size == sizeof(*BusInterface));
  107. }
  108. IoFreeIrp(irp);
  109. // get the bus interface
  110. return ntStatus;
  111. }
  112. NTSTATUS
  113. USBD_CreateDeviceEx(
  114. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  115. IN OUT PUSB_DEVICE_HANDLE *DeviceData,
  116. IN PDEVICE_OBJECT RootHubPdo,
  117. IN ULONG MaxPacketSize_Endpoint0,
  118. IN OUT PULONG DeviceHackFlags,
  119. IN USHORT PortStatus,
  120. IN USHORT PortNumber
  121. )
  122. /*++
  123. Routine Description:
  124. Arguments:
  125. Return Value:
  126. NT status code.
  127. --*/
  128. {
  129. NTSTATUS ntStatus;
  130. PUSB_DEVICE_HANDLE hubDeviceHandle;
  131. PUSB_HUB_BUS_INTERFACE busIf;
  132. // note no device extension for USBD if running on
  133. // usb 2 stack
  134. // If the HUB was ever reset through USBH_ResetDevice, the HUB PDO
  135. // DeviceExtensionPort->DeviceData could have changed. Instead of trying
  136. // to propagate a change in the HUB PDO DeviceExtensionPort->DeviceData
  137. // through to the HUB FDO DeviceExtensionHub when a change happens, let's
  138. // just retrieve the HubDeviceHandle every time we use it (which is only
  139. // in this routine) instead of keeping a cached copy.
  140. //
  141. hubDeviceHandle =
  142. USBH_SyncGetDeviceHandle(DeviceExtensionHub->TopOfStackDeviceObject);
  143. busIf = &DeviceExtensionHub->BusIf;
  144. if (!busIf->CreateUsbDevice) {
  145. ntStatus = STATUS_NOT_IMPLEMENTED;
  146. USBH_ASSERT(FALSE);
  147. } else {
  148. ntStatus = busIf->CreateUsbDevice(busIf->BusContext,
  149. DeviceData,
  150. hubDeviceHandle,
  151. PortStatus,
  152. // ttnumber
  153. PortNumber);
  154. }
  155. // get the hack flags
  156. return ntStatus;
  157. }
  158. NTSTATUS
  159. USBD_InitUsb2Hub(
  160. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub
  161. )
  162. /*++
  163. Routine Description:
  164. Arguments:
  165. Return Value:
  166. NT status code.
  167. --*/
  168. {
  169. NTSTATUS ntStatus;
  170. PUSB_DEVICE_HANDLE hubDeviceHandle;
  171. PUSB_HUB_BUS_INTERFACE busIf;
  172. ULONG ttCount = 1;
  173. // note no device extension for USBD if running on
  174. // usb 2 stack
  175. // should only call this on a usb 2.0 hub
  176. USBH_ASSERT(DeviceExtensionHub->HubFlags & HUBFLAG_USB20_HUB);
  177. if (DeviceExtensionHub->HubFlags & HUBFLAG_USB20_MULTI_TT) {
  178. PUSB_HUB_DESCRIPTOR hubDescriptor;
  179. hubDescriptor = DeviceExtensionHub->HubDescriptor;
  180. USBH_ASSERT(NULL != hubDescriptor);
  181. ttCount = hubDescriptor->bNumberOfPorts;
  182. }
  183. // If the HUB was ever reset through USBH_ResetDevice, the HUB PDO
  184. // DeviceExtensionPort->DeviceData could have changed. Instead of trying
  185. // to propagate a change in the HUB PDO DeviceExtensionPort->DeviceData
  186. // through to the HUB FDO DeviceExtensionHub when a change happens, let's
  187. // just retrieve the HubDeviceHandle every time we use it (which is only
  188. // in this routine) instead of keeping a cached copy.
  189. //
  190. hubDeviceHandle =
  191. USBH_SyncGetDeviceHandle(DeviceExtensionHub->TopOfStackDeviceObject);
  192. busIf = &DeviceExtensionHub->BusIf;
  193. if (!busIf->Initialize20Hub) {
  194. ntStatus = STATUS_NOT_IMPLEMENTED;
  195. USBH_ASSERT(FALSE);
  196. } else {
  197. ntStatus = busIf->Initialize20Hub(busIf->BusContext,
  198. hubDeviceHandle,
  199. ttCount);
  200. }
  201. return ntStatus;
  202. }
  203. NTSTATUS
  204. USBD_InitializeDeviceEx(
  205. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  206. IN PUSB_DEVICE_HANDLE DeviceData,
  207. IN PDEVICE_OBJECT RootHubPdo,
  208. IN OUT PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
  209. IN ULONG DeviceDescriptorLength,
  210. IN OUT PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
  211. IN ULONG ConfigDescriptorLength
  212. )
  213. /*++
  214. Routine Description:
  215. Arguments:
  216. Return Value:
  217. NT status code.
  218. --*/
  219. {
  220. NTSTATUS ntStatus;
  221. PUSB_HUB_BUS_INTERFACE busIf;
  222. busIf = &DeviceExtensionHub->BusIf;
  223. if (!busIf->InitializeUsbDevice || !busIf->GetUsbDescriptors) {
  224. ntStatus = STATUS_NOT_IMPLEMENTED;
  225. USBH_ASSERT(FALSE);
  226. } else {
  227. ntStatus = busIf->InitializeUsbDevice(busIf->BusContext,
  228. DeviceData);
  229. }
  230. // if successful fetch the descriptors
  231. if (NT_SUCCESS(ntStatus)) {
  232. ntStatus = busIf->GetUsbDescriptors(busIf->BusContext,
  233. DeviceData,
  234. (PUCHAR) DeviceDescriptor,
  235. &DeviceDescriptorLength,
  236. (PUCHAR) ConfigDescriptor,
  237. &ConfigDescriptorLength);
  238. }
  239. return ntStatus;
  240. }
  241. NTSTATUS
  242. USBD_RemoveDeviceEx(
  243. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  244. IN PUSB_DEVICE_HANDLE DeviceData,
  245. IN PDEVICE_OBJECT RootHubPdo,
  246. IN ULONG Flags
  247. )
  248. /*++
  249. Routine Description:
  250. Arguments:
  251. Return Value:
  252. NT status code.
  253. --*/
  254. {
  255. NTSTATUS ntStatus;
  256. PUSB_HUB_BUS_INTERFACE busIf;
  257. busIf = &DeviceExtensionHub->BusIf;
  258. // flags are currently not used by usb2 stack
  259. if (!busIf->RemoveUsbDevice) {
  260. ntStatus = STATUS_NOT_IMPLEMENTED;
  261. USBH_ASSERT(FALSE);
  262. } else {
  263. ntStatus = busIf->RemoveUsbDevice(busIf->BusContext,
  264. DeviceData,
  265. Flags);
  266. }
  267. return ntStatus;
  268. }
  269. NTSTATUS
  270. USBD_GetDeviceInformationEx(
  271. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  272. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  273. IN PUSB_NODE_CONNECTION_INFORMATION_EX DeviceInformation,
  274. IN ULONG DeviceInformationLength,
  275. IN PUSB_DEVICE_HANDLE DeviceData
  276. )
  277. /*
  278. This function maps the new port service on to the
  279. old hub api.
  280. */
  281. {
  282. NTSTATUS ntStatus;
  283. PUSB_HUB_BUS_INTERFACE busIf;
  284. ULONG length, lengthCopied;
  285. ULONG i, need;
  286. PUSB_DEVICE_INFORMATION_0 level_0 = NULL;
  287. PUSB_NODE_CONNECTION_INFORMATION_EX localDeviceInfo;
  288. busIf = &DeviceExtensionHub->BusIf;
  289. if (!busIf->QueryDeviceInformation) {
  290. ntStatus = STATUS_NOT_IMPLEMENTED;
  291. USBH_ASSERT(FALSE);
  292. return ntStatus;
  293. }
  294. // call the new API and map the data to the old format
  295. // USBH_KdPrint((0, "'Warning: Caller is using old style IOCTL.\n"));
  296. // USBH_KdPrint((0, "'If this is a WinOS component or Test Application please fix it.\n"));
  297. // TEST_TRAP();
  298. length = sizeof(*level_0);
  299. do {
  300. ntStatus = STATUS_SUCCESS;
  301. level_0 = UsbhExAllocatePool(PagedPool, length);
  302. if (level_0 == NULL) {
  303. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  304. }
  305. if (NT_SUCCESS(ntStatus)) {
  306. level_0->InformationLevel = 0;
  307. ntStatus = busIf->QueryDeviceInformation(busIf->BusContext,
  308. DeviceData,
  309. level_0,
  310. length,
  311. &lengthCopied);
  312. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  313. length = level_0->ActualLength;
  314. UsbhExFreePool(level_0);
  315. }
  316. }
  317. } while (ntStatus == STATUS_BUFFER_TOO_SMALL);
  318. // do we have enough to satisfiy the API?
  319. need = level_0->NumberOfOpenPipes * sizeof(USB_PIPE_INFO) +
  320. sizeof(USB_NODE_CONNECTION_INFORMATION);
  321. localDeviceInfo = UsbhExAllocatePool(PagedPool, need);
  322. if (localDeviceInfo == NULL) {
  323. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  324. }
  325. if (NT_SUCCESS(ntStatus)) {
  326. USBH_KdPrint((2, "'level_0 %x\n", level_0 ));
  327. // BUGBUG
  328. // DeviceInformation has some preset fields, save them
  329. // in the loacl info buffer
  330. localDeviceInfo->DeviceIsHub =
  331. DeviceInformation->DeviceIsHub;
  332. localDeviceInfo->ConnectionIndex =
  333. DeviceInformation->ConnectionIndex;
  334. localDeviceInfo->ConnectionStatus =
  335. DeviceInformation->ConnectionStatus;
  336. localDeviceInfo->DeviceIsHub =
  337. DeviceInformation->DeviceIsHub;
  338. // map to the old format
  339. localDeviceInfo->DeviceDescriptor =
  340. level_0->DeviceDescriptor;
  341. localDeviceInfo->CurrentConfigurationValue =
  342. level_0->CurrentConfigurationValue;
  343. localDeviceInfo->Speed = (UCHAR) level_0->DeviceSpeed;
  344. // draw this from our extension
  345. localDeviceInfo->DeviceIsHub =
  346. (DeviceExtensionPort->PortPdoFlags & PORTPDO_DEVICE_IS_HUB)
  347. ? TRUE : FALSE;
  348. localDeviceInfo->DeviceAddress =
  349. level_0->DeviceAddress;
  350. localDeviceInfo->NumberOfOpenPipes =
  351. level_0->NumberOfOpenPipes;
  352. // BUGBUG - hardcode to 'connected' ?
  353. // is this used by callers?
  354. // DeviceInformation->ConnectionStatus =
  355. // DeviceConnected;
  356. for (i=0; i< level_0->NumberOfOpenPipes; i++) {
  357. localDeviceInfo->PipeList[i].EndpointDescriptor =
  358. level_0->PipeList[i].EndpointDescriptor;
  359. localDeviceInfo->PipeList[i].ScheduleOffset =
  360. level_0->PipeList[i].ScheduleOffset;
  361. }
  362. }
  363. if (level_0 != NULL) {
  364. UsbhExFreePool(level_0);
  365. level_0 = NULL;
  366. }
  367. if (localDeviceInfo != NULL) {
  368. if (need > DeviceInformationLength) {
  369. // return what we can
  370. RtlCopyMemory(DeviceInformation,
  371. localDeviceInfo,
  372. DeviceInformationLength);
  373. ntStatus = STATUS_BUFFER_TOO_SMALL;
  374. } else {
  375. // return what is appropriate
  376. RtlCopyMemory(DeviceInformation,
  377. localDeviceInfo ,
  378. need);
  379. }
  380. UsbhExFreePool(localDeviceInfo);
  381. localDeviceInfo = NULL;
  382. }
  383. return ntStatus;
  384. }
  385. //ULONG
  386. //USBD_GetHackFlags(
  387. // IN PDEVICE_EXTENSION_HUB DeviceExtensionHub
  388. // )
  389. //{
  390. // NTSTATUS ntStatus;
  391. // ULONG flags;
  392. // PUSB_HUB_BUS_INTERFACE busIf;
  393. //
  394. // busIf = &DeviceExtensionHub->BusIf;
  395. //
  396. // // flags are currently not used by usb2 stack
  397. //
  398. // ntStatus = busIf->GetPortHackFlags(busIf->BusContext, &flags);
  399. //
  400. // return flags;
  401. //}
  402. NTSTATUS
  403. USBD_MakePdoNameEx(
  404. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  405. IN OUT PUNICODE_STRING PdoNameUnicodeString,
  406. IN ULONG Index
  407. )
  408. /*++
  409. Routine Description:
  410. This service Creates a name for a PDO created by the HUB
  411. Arguments:
  412. Return Value:
  413. --*/
  414. {
  415. PWCHAR nameBuffer = NULL;
  416. WCHAR rootName[] = L"\\Device\\USBPDO-";
  417. UNICODE_STRING idUnicodeString;
  418. WCHAR buffer[32];
  419. NTSTATUS ntStatus = STATUS_SUCCESS;
  420. USHORT length;
  421. length = sizeof(buffer)+sizeof(rootName);
  422. //
  423. // use ExAllocate because client will free it
  424. //
  425. nameBuffer = UsbhExAllocatePool(PagedPool, length);
  426. if (nameBuffer) {
  427. RtlCopyMemory(nameBuffer, rootName, sizeof(rootName));
  428. RtlInitUnicodeString(PdoNameUnicodeString,
  429. nameBuffer);
  430. PdoNameUnicodeString->MaximumLength =
  431. length;
  432. RtlInitUnicodeString(&idUnicodeString,
  433. &buffer[0]);
  434. idUnicodeString.MaximumLength =
  435. sizeof(buffer);
  436. ntStatus = RtlIntegerToUnicodeString(
  437. Index,
  438. 10,
  439. &idUnicodeString);
  440. if (NT_SUCCESS(ntStatus)) {
  441. ntStatus = RtlAppendUnicodeStringToString(PdoNameUnicodeString,
  442. &idUnicodeString);
  443. }
  444. USBH_KdPrint((2, "'USBD_MakeNodeName string = %x\n",
  445. PdoNameUnicodeString));
  446. } else {
  447. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  448. }
  449. if (!NT_SUCCESS(ntStatus) && nameBuffer) {
  450. UsbhExFreePool(nameBuffer);
  451. }
  452. return ntStatus;
  453. }
  454. NTSTATUS
  455. USBD_RestoreDeviceEx(
  456. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  457. IN OUT PUSB_DEVICE_HANDLE OldDeviceData,
  458. IN OUT PUSB_DEVICE_HANDLE NewDeviceData,
  459. IN PDEVICE_OBJECT RootHubPdo
  460. )
  461. {
  462. NTSTATUS ntStatus;
  463. PUSB_HUB_BUS_INTERFACE busIf;
  464. busIf = &DeviceExtensionHub->BusIf;
  465. if (!busIf->RestoreUsbDevice) {
  466. ntStatus = STATUS_NOT_IMPLEMENTED;
  467. USBH_ASSERT(FALSE);
  468. } else {
  469. ntStatus = busIf->RestoreUsbDevice(busIf->BusContext,
  470. OldDeviceData,
  471. NewDeviceData);
  472. }
  473. return ntStatus;
  474. }
  475. NTSTATUS
  476. USBD_QuerySelectiveSuspendEnabled(
  477. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  478. IN OUT PBOOLEAN SelectiveSuspendEnabled
  479. )
  480. {
  481. NTSTATUS ntStatus;
  482. PUSB_HUB_BUS_INTERFACE busIf;
  483. USB_CONTROLLER_INFORMATION_0 controllerInfo;
  484. ULONG dataLen = 0;
  485. controllerInfo.InformationLevel = 0;
  486. busIf = &DeviceExtensionHub->BusIf;
  487. if (!busIf->GetControllerInformation) {
  488. ntStatus = STATUS_NOT_IMPLEMENTED;
  489. USBH_ASSERT(FALSE);
  490. } else {
  491. ntStatus = busIf->GetControllerInformation(busIf->BusContext,
  492. &controllerInfo,
  493. sizeof(controllerInfo),
  494. &dataLen);
  495. }
  496. USBH_ASSERT(dataLen);
  497. if (dataLen) {
  498. *SelectiveSuspendEnabled = controllerInfo.SelectiveSuspendEnabled;
  499. }
  500. return ntStatus;
  501. }
  502. VOID
  503. USBHUB_RhHubCallBack(
  504. PDEVICE_EXTENSION_HUB DeviceExtensionHub
  505. )
  506. {
  507. DeviceExtensionHub->HubFlags |= HUBFLAG_OK_TO_ENUMERATE;
  508. // if irp is null'ed out then it must have been stopped or removed before
  509. // our callback we just check for NULL here instead of the dozen or so
  510. // flags the hub has.
  511. if (DeviceExtensionHub->Irp != NULL) {
  512. USBH_SubmitInterruptTransfer(DeviceExtensionHub);
  513. USBH_IoInvalidateDeviceRelations(DeviceExtensionHub->PhysicalDeviceObject,
  514. BusRelations);
  515. }
  516. }
  517. NTSTATUS
  518. USBD_RegisterRhHubCallBack(
  519. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub
  520. )
  521. {
  522. NTSTATUS ntStatus;
  523. PUSB_HUB_BUS_INTERFACE busIf;
  524. busIf = &DeviceExtensionHub->BusIf;
  525. if (!busIf->RootHubInitNotification) {
  526. ntStatus = STATUS_NOT_IMPLEMENTED;
  527. USBH_ASSERT(FALSE);
  528. } else {
  529. ntStatus = busIf->RootHubInitNotification(busIf->BusContext,
  530. DeviceExtensionHub,
  531. USBHUB_RhHubCallBack);
  532. }
  533. return ntStatus;
  534. }
  535. NTSTATUS
  536. USBD_UnRegisterRhHubCallBack(
  537. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub
  538. )
  539. {
  540. NTSTATUS ntStatus;
  541. PUSB_HUB_BUS_INTERFACE busIf;
  542. busIf = &DeviceExtensionHub->BusIf;
  543. if (!busIf->RootHubInitNotification) {
  544. ntStatus = STATUS_NOT_IMPLEMENTED;
  545. USBH_ASSERT(FALSE);
  546. } else {
  547. ntStatus = busIf->RootHubInitNotification(busIf->BusContext,
  548. NULL,
  549. NULL);
  550. }
  551. return ntStatus;
  552. }
  553. NTSTATUS
  554. USBD_SetSelectiveSuspendEnabled(
  555. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  556. IN BOOLEAN SelectiveSuspendEnabled
  557. )
  558. {
  559. NTSTATUS ntStatus;
  560. PUSB_HUB_BUS_INTERFACE busIf;
  561. busIf = &DeviceExtensionHub->BusIf;
  562. if (!busIf->ControllerSelectiveSuspend) {
  563. ntStatus = STATUS_NOT_IMPLEMENTED;
  564. USBH_ASSERT(FALSE);
  565. } else {
  566. ntStatus = busIf->ControllerSelectiveSuspend(busIf->BusContext,
  567. SelectiveSuspendEnabled);
  568. }
  569. return ntStatus;
  570. }
  571. BOOLEAN
  572. USBH_ValidateConfigurationDescriptor(
  573. PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  574. USBD_STATUS *UsbdStatus
  575. )
  576. /*++
  577. Routine Description:
  578. Validate a configuration descriptor
  579. Arguments:
  580. ConfigurationDescriptor -
  581. Urb -
  582. Return Value:
  583. TRUE if it looks valid
  584. --*/
  585. {
  586. BOOLEAN valid = TRUE;
  587. if (ConfigurationDescriptor->bDescriptorType !=
  588. USB_CONFIGURATION_DESCRIPTOR_TYPE) {
  589. valid = FALSE;
  590. *UsbdStatus = USBD_STATUS_INAVLID_CONFIGURATION_DESCRIPTOR;
  591. }
  592. // USB 1.1, Section 9.5 Descriptors:
  593. //
  594. // If a descriptor returns with a value in its length field that is
  595. // less than defined by this specification, the descriptor is invalid and
  596. // should be rejected by the host. If the descriptor returns with a
  597. // value in its length field that is greater than defined by this
  598. // specification, the extra bytes are ignored by the host, but the next
  599. // descriptor is located using the length returned rather than the length
  600. // expected.
  601. if (ConfigurationDescriptor->bLength <
  602. sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
  603. valid = FALSE;
  604. *UsbdStatus = USBD_STATUS_INAVLID_CONFIGURATION_DESCRIPTOR;
  605. }
  606. return valid;
  607. }
  608. NTSTATUS
  609. USBHUB_GetBusInterfaceUSBDI(
  610. IN PDEVICE_OBJECT HubPdo,
  611. IN PUSB_BUS_INTERFACE_USBDI_V2 BusInterface
  612. )
  613. /*++
  614. Routine Description:
  615. Arguments:
  616. Return Value:
  617. returns success if USB2 stack
  618. --*/
  619. {
  620. PIO_STACK_LOCATION nextStack;
  621. PIRP irp;
  622. NTSTATUS ntStatus;
  623. KEVENT event;
  624. irp = IoAllocateIrp(HubPdo->StackSize, FALSE);
  625. if (!irp) {
  626. return STATUS_UNSUCCESSFUL;
  627. }
  628. // All PnP IRP's need the Status field initialized to STATUS_NOT_SUPPORTED.
  629. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  630. KeInitializeEvent(&event, NotificationEvent, FALSE);
  631. IoSetCompletionRoutine(irp,
  632. USBD_DeferIrpCompletion,
  633. &event,
  634. TRUE,
  635. TRUE,
  636. TRUE);
  637. nextStack = IoGetNextIrpStackLocation(irp);
  638. ASSERT(nextStack != NULL);
  639. nextStack->MajorFunction= IRP_MJ_PNP;
  640. nextStack->MinorFunction= IRP_MN_QUERY_INTERFACE;
  641. // init busif
  642. //busIf->
  643. nextStack->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface;
  644. // this is the device handle, filled in as we pass down the
  645. // stack
  646. nextStack->Parameters.QueryInterface.InterfaceSpecificData =
  647. NULL;
  648. nextStack->Parameters.QueryInterface.InterfaceType =
  649. &USB_BUS_INTERFACE_USBDI_GUID;
  650. nextStack->Parameters.QueryInterface.Size =
  651. sizeof(*BusInterface);
  652. nextStack->Parameters.QueryInterface.Version =
  653. USB_BUSIF_USBDI_VERSION_2;
  654. ntStatus = IoCallDriver(HubPdo,
  655. irp);
  656. if (ntStatus == STATUS_PENDING) {
  657. KeWaitForSingleObject(
  658. &event,
  659. Suspended,
  660. KernelMode,
  661. FALSE,
  662. NULL);
  663. ntStatus = irp->IoStatus.Status;
  664. }
  665. if (NT_SUCCESS(ntStatus)) {
  666. // we have a bus interface
  667. ASSERT(BusInterface->Version == USB_BUSIF_USBDI_VERSION_2);
  668. ASSERT(BusInterface->Size == sizeof(*BusInterface));
  669. }
  670. IoFreeIrp(irp);
  671. // get the bus interface
  672. return ntStatus;
  673. }
  674. NTSTATUS
  675. USBHUB_GetBusInfoDevice(
  676. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  677. IN PDEVICE_EXTENSION_PORT DeviceExtensionPort,
  678. IN PUSB_BUS_NOTIFICATION BusInfo
  679. )
  680. /*++
  681. Routine Description:
  682. Return the bus information relative to a specific device
  683. Arguments:
  684. Return Value:
  685. --*/
  686. {
  687. NTSTATUS ntStatus;
  688. PUSB_HUB_BUS_INTERFACE busIf;
  689. PVOID busContext;
  690. busIf = &DeviceExtensionHub->BusIf;
  691. busContext = busIf->GetDeviceBusContext(busIf->BusContext,
  692. DeviceExtensionPort->DeviceData);
  693. // get the TT handle for this device and query the
  694. // bus information relative to it
  695. ntStatus = USBHUB_GetBusInfo(DeviceExtensionHub,
  696. BusInfo,
  697. busContext);
  698. return ntStatus;
  699. }
  700. NTSTATUS
  701. USBHUB_GetBusInfo(
  702. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  703. IN PUSB_BUS_NOTIFICATION BusInfo,
  704. IN PVOID BusContext
  705. )
  706. /*++
  707. Routine Description:
  708. Arguments:
  709. Return Value:
  710. --*/
  711. {
  712. PUSB_BUS_INFORMATION_LEVEL_1 level_1;
  713. PUSB_BUS_INTERFACE_USBDI_V2 busIf;
  714. ULONG length, actualLength;
  715. NTSTATUS ntStatus;
  716. busIf = &DeviceExtensionHub->UsbdiBusIf;
  717. if (!busIf->QueryBusInformation) {
  718. ntStatus = STATUS_NOT_IMPLEMENTED;
  719. USBH_ASSERT(FALSE);
  720. return ntStatus;
  721. }
  722. length = sizeof(USB_BUS_INFORMATION_LEVEL_1);
  723. do {
  724. level_1 = UsbhExAllocatePool(PagedPool, length);
  725. if (level_1 != NULL) {
  726. if (BusContext == NULL) {
  727. BusContext = busIf->BusContext;
  728. }
  729. ntStatus = busIf->QueryBusInformation(BusContext,
  730. 1,
  731. level_1,
  732. &length,
  733. &actualLength);
  734. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  735. length = actualLength;
  736. UsbhExFreePool(level_1);
  737. level_1 = NULL;
  738. }
  739. } else {
  740. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  741. }
  742. } while (ntStatus == STATUS_BUFFER_TOO_SMALL);
  743. if (NT_SUCCESS(ntStatus)) {
  744. LOGENTRY(LOG_PNP, "lev1", level_1, 0, 0);
  745. BusInfo->TotalBandwidth = level_1->TotalBandwidth;
  746. BusInfo->ConsumedBandwidth = level_1->ConsumedBandwidth;
  747. /* length of the UNICODE symbolic name (in bytes) for the controller
  748. that this device is attached to.
  749. not including NULL */
  750. BusInfo->ControllerNameLength = level_1->ControllerNameLength;
  751. UsbhExFreePool(level_1);
  752. }
  753. return ntStatus;
  754. }
  755. NTSTATUS
  756. USBHUB_GetExtendedHubInfo(
  757. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  758. IN PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo
  759. )
  760. /*++
  761. Routine Description:
  762. Arguments:
  763. Return Value:
  764. --*/
  765. {
  766. NTSTATUS ntStatus;
  767. PUSB_HUB_BUS_INTERFACE busIf;
  768. PVOID busContext;
  769. ULONG length;
  770. busIf = &DeviceExtensionHub->BusIf;
  771. ntStatus = busIf->GetExtendedHubInformation(busIf->BusContext,
  772. DeviceExtensionHub->PhysicalDeviceObject,
  773. ExtendedHubInfo,
  774. sizeof(*ExtendedHubInfo),
  775. &length);
  776. return ntStatus;
  777. }
  778. PUSB_DEVICE_HANDLE
  779. USBH_SyncGetDeviceHandle(
  780. IN PDEVICE_OBJECT DeviceObject
  781. )
  782. /* ++
  783. *
  784. * Routine Description:
  785. *
  786. * Arguments:
  787. *
  788. * Return Value:
  789. *
  790. * NTSTATUS
  791. *
  792. * -- */
  793. {
  794. NTSTATUS ntStatus, status;
  795. PIRP irp;
  796. KEVENT event;
  797. IO_STATUS_BLOCK ioStatus;
  798. PIO_STACK_LOCATION nextStack;
  799. PUSB_DEVICE_HANDLE handle = NULL;
  800. PAGED_CODE();
  801. USBH_KdPrint((2,"'enter USBH_SyncGetDeviceHandle\n"));
  802. //
  803. // issue a synchronous request to the RootHubBdo
  804. //
  805. KeInitializeEvent(&event, NotificationEvent, FALSE);
  806. irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
  807. DeviceObject,
  808. NULL,
  809. 0,
  810. NULL,
  811. 0,
  812. TRUE, // INTERNAL
  813. &event,
  814. &ioStatus);
  815. if (NULL == irp) {
  816. goto USBH_SyncGetDeviceHandle_Done;
  817. }
  818. //
  819. // Call the class driver to perform the operation. If the returned
  820. // status
  821. // is PENDING, wait for the request to complete.
  822. //
  823. nextStack = IoGetNextIrpStackLocation(irp);
  824. //
  825. // pass the URB to the USBD 'class driver'
  826. //
  827. nextStack->Parameters.Others.Argument1 = &handle;
  828. ntStatus = IoCallDriver(DeviceObject, irp);
  829. USBH_KdPrint((2,"'return from IoCallDriver USBD %x\n", ntStatus));
  830. if (ntStatus == STATUS_PENDING) {
  831. USBH_KdPrint((2,"'Wait for single object\n"));
  832. status = KeWaitForSingleObject(&event,
  833. Suspended,
  834. KernelMode,
  835. FALSE,
  836. NULL);
  837. USBH_KdPrint((2,"'Wait for single object, returned %x\n", status));
  838. } else {
  839. ioStatus.Status = ntStatus;
  840. }
  841. ntStatus = ioStatus.Status;
  842. USBH_KdPrint((2,"'exit USBH_SyncGetDeviceHandle (%x)\n", ntStatus));
  843. USBH_SyncGetDeviceHandle_Done:
  844. return handle;
  845. }
  846. USB_DEVICE_TYPE
  847. USBH_GetDeviceType(
  848. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  849. IN PUSB_DEVICE_HANDLE DeviceData
  850. )
  851. /*
  852. This function maps the new port service on to the
  853. old hub api.
  854. */
  855. {
  856. NTSTATUS ntStatus;
  857. PUSB_HUB_BUS_INTERFACE busIf;
  858. ULONG length, lengthCopied;
  859. ULONG i, need;
  860. PUSB_DEVICE_INFORMATION_0 level_0 = NULL;
  861. // if all else fails assum it is 11
  862. USB_DEVICE_TYPE deviceType = Usb11Device;
  863. busIf = &DeviceExtensionHub->BusIf;
  864. if (!busIf->QueryDeviceInformation) {
  865. ntStatus = STATUS_NOT_IMPLEMENTED;
  866. USBH_ASSERT(FALSE);
  867. return ntStatus;
  868. }
  869. length = sizeof(*level_0);
  870. do {
  871. ntStatus = STATUS_SUCCESS;
  872. level_0 = UsbhExAllocatePool(PagedPool, length);
  873. if (level_0 == NULL) {
  874. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  875. }
  876. if (NT_SUCCESS(ntStatus)) {
  877. level_0->InformationLevel = 0;
  878. ntStatus = busIf->QueryDeviceInformation(busIf->BusContext,
  879. DeviceData,
  880. level_0,
  881. length,
  882. &lengthCopied);
  883. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  884. length = level_0->ActualLength;
  885. UsbhExFreePool(level_0);
  886. }
  887. }
  888. } while (ntStatus == STATUS_BUFFER_TOO_SMALL);
  889. // do we have enough to satisfiy the API?
  890. need = level_0->NumberOfOpenPipes * sizeof(USB_PIPE_INFO) +
  891. sizeof(USB_NODE_CONNECTION_INFORMATION);
  892. if (NT_SUCCESS(ntStatus)) {
  893. deviceType = level_0->DeviceType;
  894. }
  895. if (level_0 != NULL) {
  896. UsbhExFreePool(level_0);
  897. level_0 = NULL;
  898. }
  899. USBH_KdPrint((2,"'exit USBH_GetDeviceType (%x)\n", deviceType));
  900. return deviceType;
  901. }
  902. VOID
  903. USBH_InitializeUSB2Hub(
  904. PDEVICE_EXTENSION_HUB DeviceExtensionHub
  905. )
  906. /*++
  907. Routine Description:
  908. Arguments:
  909. Return Value:
  910. --*/
  911. {
  912. NTSTATUS ntStatus;
  913. PUSB_DEVICE_HANDLE hubDeviceHandle;
  914. // NOTE: if we are running on the old 1.1 stack a NULL
  915. // is returned
  916. hubDeviceHandle =
  917. USBH_SyncGetDeviceHandle(DeviceExtensionHub->TopOfStackDeviceObject);
  918. // if we are a USB 2 hub then set the hub flag so we ignore
  919. // failed resets
  920. if (hubDeviceHandle != NULL &&
  921. USBH_GetDeviceType(DeviceExtensionHub,
  922. hubDeviceHandle) == Usb20Device) {
  923. DeviceExtensionHub->HubFlags |= HUBFLAG_USB20_HUB;
  924. }
  925. #ifdef TEST_2X_UI
  926. if (IS_ROOT_HUB(DeviceExtensionHub)) {
  927. // To test the UI, mark the root hub as 2.x capable.
  928. DeviceExtensionHub->HubFlags |= HUBFLAG_USB20_HUB;
  929. }
  930. #endif
  931. }
  932. NTSTATUS
  933. USBHUB_GetControllerName(
  934. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  935. IN PUSB_HUB_NAME Buffer,
  936. IN ULONG BufferLength
  937. )
  938. /*++
  939. Routine Description:
  940. Arguments:
  941. Return Value:
  942. --*/
  943. {
  944. PUSB_BUS_INFORMATION_LEVEL_1 level_1;
  945. PUSB_BUS_INTERFACE_USBDI_V2 busIf;
  946. ULONG lenToCopy, length, actualLength;
  947. NTSTATUS ntStatus;
  948. busIf = &DeviceExtensionHub->UsbdiBusIf;
  949. if (!busIf->QueryBusInformation) {
  950. ntStatus = STATUS_NOT_IMPLEMENTED;
  951. USBH_ASSERT(FALSE);
  952. return ntStatus;
  953. }
  954. length = sizeof(USB_BUS_INFORMATION_LEVEL_1);
  955. do {
  956. level_1 = UsbhExAllocatePool(PagedPool, length);
  957. if (level_1 != NULL) {
  958. ntStatus = busIf->QueryBusInformation(busIf->BusContext,
  959. 1,
  960. level_1,
  961. &length,
  962. &actualLength);
  963. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  964. length = actualLength;
  965. UsbhExFreePool(level_1);
  966. level_1 = NULL;
  967. }
  968. } else {
  969. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  970. }
  971. } while (ntStatus == STATUS_BUFFER_TOO_SMALL);
  972. if (NT_SUCCESS(ntStatus)) {
  973. LOGENTRY(LOG_PNP, "lev1", level_1, 0, 0);
  974. // not sure if BufferLength includes size of the
  975. // ActualLength field, we will assume it does
  976. Buffer->ActualLength = level_1->ControllerNameLength;
  977. if ((BufferLength - sizeof(Buffer->ActualLength))
  978. >= level_1->ControllerNameLength) {
  979. lenToCopy = level_1->ControllerNameLength;
  980. } else {
  981. lenToCopy = BufferLength - sizeof(Buffer->ActualLength);
  982. }
  983. // copy what we can
  984. RtlCopyMemory(&Buffer->HubName[0],
  985. &level_1->ControllerNameUnicodeString[0],
  986. lenToCopy);
  987. UsbhExFreePool(level_1);
  988. }
  989. return ntStatus;
  990. }
  991. NTSTATUS
  992. USBHUB_GetRootHubName(
  993. IN PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  994. IN PVOID Buffer,
  995. IN PULONG BufferLength
  996. )
  997. {
  998. NTSTATUS ntStatus;
  999. PUSB_HUB_BUS_INTERFACE busIf;
  1000. busIf = &DeviceExtensionHub->BusIf;
  1001. if (!busIf->GetRootHubSymbolicName) {
  1002. ntStatus = STATUS_NOT_IMPLEMENTED;
  1003. USBH_ASSERT(FALSE);
  1004. } else {
  1005. ntStatus = busIf->GetRootHubSymbolicName(
  1006. busIf->BusContext,
  1007. Buffer,
  1008. *BufferLength,
  1009. BufferLength);
  1010. }
  1011. return ntStatus;
  1012. }
  1013. VOID
  1014. USBHUB_FlushAllTransfers(
  1015. PDEVICE_EXTENSION_HUB DeviceExtensionHub
  1016. )
  1017. {
  1018. NTSTATUS ntStatus;
  1019. PUSB_HUB_BUS_INTERFACE busIf;
  1020. busIf = &DeviceExtensionHub->BusIf;
  1021. if (!busIf->FlushTransfers) {
  1022. ntStatus = STATUS_NOT_IMPLEMENTED;
  1023. USBH_ASSERT(FALSE);
  1024. } else {
  1025. busIf->FlushTransfers(busIf->BusContext,
  1026. NULL);
  1027. }
  1028. return;
  1029. }
  1030. VOID
  1031. USBHUB_SetDeviceHandleData(
  1032. PDEVICE_EXTENSION_HUB DeviceExtensionHub,
  1033. PDEVICE_OBJECT PdoDeviceObject,
  1034. PVOID DeviceData
  1035. )
  1036. {
  1037. PUSB_HUB_BUS_INTERFACE busIf;
  1038. busIf = &DeviceExtensionHub->BusIf;
  1039. // associate this PDO with the device handle
  1040. // (if we can)
  1041. if (!busIf->SetDeviceHandleData) {
  1042. USBH_ASSERT(FALSE);
  1043. } else {
  1044. busIf->SetDeviceHandleData(busIf->BusContext,
  1045. DeviceData,
  1046. PdoDeviceObject);
  1047. }
  1048. return;
  1049. }
  1050. #endif