NTSTATUS NTAPI UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; ULONG MinorFunction; ULONG_PTR Information = 0; PHUB_DEVICE_EXTENSION DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); MinorFunction = IrpSp->MinorFunction; DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; switch (MinorFunction) { case IRP_MN_START_DEVICE: /* 0x0 */ { PURB Urb; ULONG Result = 0; PUSB_INTERFACE_DESCRIPTOR Pid; /* Theres only one descriptor on hub */ USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; PURB ConfigUrb = NULL; /* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */ DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); /* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG); RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY)); /* Get the hubs PDO */ QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo); ASSERT(DeviceExtension->RootHubPdo); ASSERT(DeviceExtension->RootHubFdo); DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo); /* Send the START_DEVICE irp down to the PDO of RootHub */ Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to start the RootHub PDO\n"); ASSERT(FALSE); } /* Get the current number of hubs */ QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL); /* Get the Direct Call Interfaces */ Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_HUB_GUID, sizeof(USB_BUS_INTERFACE_HUB_V5), 5, (PVOID)&DeviceExtension->HubInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_USBDI_GUID, sizeof(USB_BUS_INTERFACE_USBDI_V2), 2, (PVOID)&DeviceExtension->UsbDInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } /* Get roothub device handle */ Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); return Status; } Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, &DeviceExtension->DeviceInformation, sizeof(USB_DEVICE_INFORMATION_0), &Result); DPRINT("Status %x, Result %x\n", Status, Result); DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel); DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength); DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber); DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor); DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress); DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes); /* Get roothubs device descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubDeviceDescriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n"); } DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor); /* Get roothubs configuration descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubConfigDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status); ASSERT(FALSE); } ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength); DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor); //DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength); Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubPdo, &DeviceExtension->UsbExtHubInfo, sizeof(USB_EXTHUB_INFORMATION_0), &Result); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n"); ASSERT(FALSE); } DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_DEVICE, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_DEVICE_CLASS_RESERVED, 0, 0, &DeviceExtension->HubDescriptor, NULL, sizeof(USB_HUB_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType); /* Select the configuration */ /* Get the first one */ Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor, &DeviceExtension->HubConfigDescriptor, -1, -1, -1, -1, -1); ASSERT(Pid != NULL); InterfaceList[0].InterfaceDescriptor = Pid; ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); ASSERT(ConfigUrb != NULL); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL); DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle); ExFreePool(ConfigUrb); Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1); DPRINT1("Status %x\n", Status); { int PortLoop; USHORT PortStatusAndChange[2]; for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { DPRINT1("Port %x\n", PortLoop); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_POWER, 1, 0, 0, 0, 0); Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PortStatusAndChange), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]); DPRINT1("PortChange = %x\n", PortStatusAndChange[1]); } } ExFreePool(Urb); break; } case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ { switch (IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: { PDEVICE_RELATIONS DeviceRelations = NULL; DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations); Information = (ULONG_PTR)DeviceRelations; break; } case RemovalRelations: { DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); return ForwardIrpAndForget(DeviceObject, Irp); } default: DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", IrpSp->Parameters.QueryDeviceRelations.Type); return ForwardIrpAndForget(DeviceObject, Irp); } break; } case IRP_MN_QUERY_BUS_INFORMATION: { DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n"); break; } case IRP_MN_QUERY_ID: { DPRINT1("IRP_MN_QUERY_ID\n"); break; } case IRP_MN_QUERY_CAPABILITIES: { DPRINT1("IRP_MN_QUERY_CAPABILITIES\n"); break; } default: { DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); return ForwardIrpAndForget(DeviceObject, Irp); } } Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
NTSTATUS NTAPI USBCCGP_ScanConfigurationDescriptor( IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) { PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; ULONG InterfaceIndex = 0; ULONG DescriptorCount; // // sanity checks // ASSERT(ConfigurationDescriptor); ASSERT(ConfigurationDescriptor->bNumInterfaces); // // count all interface descriptors // DescriptorCount = ConfigurationDescriptor->bNumInterfaces; // // allocate array holding the interface descriptors // FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (DescriptorCount + 1)); if (!FDODeviceExtension->InterfaceList) { // // no memory // return STATUS_INSUFFICIENT_RESOURCES; } do { // // parse configuration descriptor // InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, -1, -1, -1, -1); if (InterfaceDescriptor) { // // store in interface list // FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor; FDODeviceExtension->InterfaceListCount++; } else { DumpConfigurationDescriptor(ConfigurationDescriptor); DumpFullConfigurationDescriptor(FDODeviceExtension, ConfigurationDescriptor); // // see issue // CORE-6574 Test 3 (USB Web Cam) // if (FDODeviceExtension->DeviceDescriptor && FDODeviceExtension->DeviceDescriptor->idVendor == 0x0458 && FDODeviceExtension->DeviceDescriptor->idProduct == 0x705f) ASSERT(FALSE); } // // move to next interface // InterfaceIndex++; }while(InterfaceIndex < DescriptorCount); // // sanity check // ASSERT(FDODeviceExtension->InterfaceListCount); // // done // return STATUS_SUCCESS; }