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.

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