/* * PROJECT: ReactOS USB Port Driver * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: USBPort root hub implementation * COPYRIGHT: Copyright 2017 Vadim Galyant */ #include "usbport.h" #define NDEBUG #include #define NDEBUG_USBPORT_CORE #include "usbdebug.h" RHSTATUS NTAPI USBPORT_MPStatusToRHStatus(IN MPSTATUS MPStatus) { RHSTATUS RHStatus = RH_STATUS_SUCCESS; //DPRINT("USBPORT_MPStatusToRHStatus: MPStatus - %x\n", MPStatus); if (MPStatus) { RHStatus = (MPStatus != MP_STATUS_FAILURE); ++RHStatus; } return RHStatus; } MPSTATUS NTAPI USBPORT_RH_SetFeatureUSB2PortPower(IN PDEVICE_OBJECT FdoDevice, IN USHORT Port) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; PDEVICE_RELATIONS CompanionControllersList; PUSBPORT_REGISTRATION_PACKET CompanionPacket; PDEVICE_OBJECT CompanionFdoDevice; PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; USHORT ix; PDEVICE_OBJECT * Entry; ULONG NumController = 0; DPRINT("USBPORT_RootHub_PowerUsb2Port: FdoDevice - %p, Port - %p\n", FdoDevice, Port); FdoExtension = FdoDevice->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice, FALSE, TRUE); if (!CompanionControllersList) { Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); return MP_STATUS_SUCCESS; } Entry = &CompanionControllersList->Objects[0]; while (NumController < CompanionControllersList->Count) { CompanionFdoDevice = *Entry; CompanionFdoExtension = CompanionFdoDevice->DeviceExtension; CompanionPacket = &CompanionFdoExtension->MiniPortInterface->Packet; PdoExtension = CompanionFdoExtension->RootHubPdo->DeviceExtension; for (ix = 0; (PdoExtension->CommonExtension.PnpStateFlags & USBPORT_PNP_STATE_STARTED) && ix < PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts; ++ix) { CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt, ix + 1); } ++NumController; ++Entry; } Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); if (CompanionControllersList) { ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG); } return MP_STATUS_SUCCESS; } RHSTATUS NTAPI USBPORT_RootHubClassCommand(IN PDEVICE_OBJECT FdoDevice, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN PVOID Buffer, IN PULONG BufferLength) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; USHORT Port; USHORT Feature; MPSTATUS MPStatus; RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL; KIRQL OldIrql; DPRINT("USBPORT_RootHubClassCommand: USB command - %x, *BufferLength - %x\n", SetupPacket->bRequest, *BufferLength); FdoExtension = FdoDevice->DeviceExtension; PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; Port = SetupPacket->wIndex.W; switch (SetupPacket->bRequest) { case USB_REQUEST_GET_STATUS: { if (!Buffer) { return RHStatus; } *(PULONG)Buffer = 0; if (SetupPacket->bmRequestType.Recipient == BMREQUEST_TO_OTHER) { ASSERT(*BufferLength >= 4); if (Port > PdoExtension->RootHubDescriptors->Descriptor.bNumberOfPorts || Port <= 0 || SetupPacket->wLength < 4) { return RHStatus; } KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); MPStatus = Packet->RH_GetPortStatus(FdoExtension->MiniPortExt, SetupPacket->wIndex.W, Buffer); KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); } else { KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); MPStatus = Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, Buffer); KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); } RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); break; } case USB_REQUEST_CLEAR_FEATURE: Feature = SetupPacket->wValue.W; if ((SetupPacket->bmRequestType.Recipient) != USBPORT_RECIPIENT_PORT) { if (Feature == FEATURE_C_HUB_LOCAL_POWER) { RHStatus = RH_STATUS_SUCCESS; return RHStatus; } if (Feature == FEATURE_C_HUB_OVER_CURRENT) { MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt, 0); RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); return RHStatus; } DbgBreakPoint(); return RHStatus; } switch (Feature) { case FEATURE_PORT_ENABLE: MPStatus = Packet->RH_ClearFeaturePortEnable(FdoExtension->MiniPortExt, Port); break; case FEATURE_PORT_SUSPEND: MPStatus = Packet->RH_ClearFeaturePortSuspend(FdoExtension->MiniPortExt, Port); break; case FEATURE_PORT_POWER: MPStatus = Packet->RH_ClearFeaturePortPower(FdoExtension->MiniPortExt, Port); break; case FEATURE_C_PORT_CONNECTION: MPStatus = Packet->RH_ClearFeaturePortConnectChange(FdoExtension->MiniPortExt, Port); break; case FEATURE_C_PORT_ENABLE: MPStatus = Packet->RH_ClearFeaturePortEnableChange(FdoExtension->MiniPortExt, Port); break; case FEATURE_C_PORT_SUSPEND: MPStatus = Packet->RH_ClearFeaturePortSuspendChange(FdoExtension->MiniPortExt, Port); break; case FEATURE_C_PORT_OVER_CURRENT: MPStatus = Packet->RH_ClearFeaturePortOvercurrentChange(FdoExtension->MiniPortExt, Port); break; case FEATURE_C_PORT_RESET: MPStatus = Packet->RH_ClearFeaturePortResetChange(FdoExtension->MiniPortExt, Port); break; default: DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n", Feature); return RHStatus; } RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); break; case USB_REQUEST_SET_FEATURE: if (SetupPacket->bmRequestType.Recipient != USBPORT_RECIPIENT_PORT) { return RHStatus; } Feature = SetupPacket->wValue.W; switch (Feature) { case FEATURE_PORT_ENABLE: MPStatus = Packet->RH_SetFeaturePortEnable(FdoExtension->MiniPortExt, Port); break; case FEATURE_PORT_SUSPEND: MPStatus = Packet->RH_SetFeaturePortSuspend(FdoExtension->MiniPortExt, Port); break; case FEATURE_PORT_RESET: MPStatus = Packet->RH_SetFeaturePortReset(FdoExtension->MiniPortExt, Port); break; case FEATURE_PORT_POWER: if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2) { MPStatus = USBPORT_RH_SetFeatureUSB2PortPower(FdoDevice, Port); } else { MPStatus = Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); } break; default: DPRINT1("USBPORT_RootHubClassCommand: Not supported feature - %x\n", Feature); return RHStatus; } RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); break; case USB_REQUEST_GET_DESCRIPTOR: if (Buffer && SetupPacket->wValue.W == 0 && SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) { SIZE_T DescriptorLength; DescriptorLength = PdoExtension->RootHubDescriptors->Descriptor.bDescriptorLength; if (*BufferLength < DescriptorLength) DescriptorLength = *BufferLength; RtlCopyMemory(Buffer, &PdoExtension->RootHubDescriptors->Descriptor, DescriptorLength); *BufferLength = DescriptorLength; RHStatus = RH_STATUS_SUCCESS; } break; default: DPRINT1("USBPORT_RootHubClassCommand: Not supported USB request - %x\n", SetupPacket->bRequest); //USB_REQUEST_SET_ADDRESS 0x05 //USB_REQUEST_SET_DESCRIPTOR 0x07 //USB_REQUEST_GET_CONFIGURATION 0x08 //USB_REQUEST_SET_CONFIGURATION 0x09 //USB_REQUEST_GET_INTERFACE 0x0A //USB_REQUEST_SET_INTERFACE 0x0B //USB_REQUEST_SYNC_FRAME 0x0C break; } return RHStatus; } RHSTATUS NTAPI USBPORT_RootHubStandardCommand(IN PDEVICE_OBJECT FdoDevice, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN PVOID Buffer, IN OUT PULONG TransferLength) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; SIZE_T Length; PVOID Descriptor; SIZE_T DescriptorLength; MPSTATUS MPStatus; RHSTATUS RHStatus = RH_STATUS_UNSUCCESSFUL; KIRQL OldIrql; DPRINT("USBPORT_RootHubStandardCommand: USB command - %x, TransferLength - %p\n", SetupPacket->bRequest, TransferLength); FdoExtension = FdoDevice->DeviceExtension; PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; switch (SetupPacket->bRequest) { case USB_REQUEST_GET_DESCRIPTOR: if (SetupPacket->wValue.LowByte || !(SetupPacket->bmRequestType.Dir)) { return RHStatus; } switch (SetupPacket->wValue.HiByte) { case USB_DEVICE_DESCRIPTOR_TYPE: Descriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor; DescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR); break; case USB_CONFIGURATION_DESCRIPTOR_TYPE: Descriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor; DescriptorLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR); break; default: DPRINT1("USBPORT_RootHubStandardCommand: Not supported Descriptor Type - %x\n", SetupPacket->wValue.HiByte); return RHStatus; } if (!Descriptor) { return RHStatus; } if (*TransferLength >= DescriptorLength) Length = DescriptorLength; else Length = *TransferLength; RtlCopyMemory(Buffer, Descriptor, Length); *TransferLength = Length; RHStatus = RH_STATUS_SUCCESS; break; case USB_REQUEST_GET_STATUS: if (!SetupPacket->wValue.W && SetupPacket->wLength == sizeof(USHORT) && !SetupPacket->wIndex.W && SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST) { KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); MPStatus = Packet->RH_GetStatus(FdoExtension->MiniPortExt, Buffer); KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); *TransferLength = sizeof(USHORT); RHStatus = USBPORT_MPStatusToRHStatus(MPStatus); } break; case USB_REQUEST_GET_CONFIGURATION: if (SetupPacket->wValue.W || SetupPacket->wIndex.W || SetupPacket->wLength != 1 || SetupPacket->bmRequestType.Dir == BMREQUEST_HOST_TO_DEVICE) { return RHStatus; } Length = 0; if (*TransferLength >= 1) { Length = 1; RtlCopyMemory(Buffer, &PdoExtension->ConfigurationValue, Length); } *TransferLength = Length; RHStatus = RH_STATUS_SUCCESS; break; case USB_REQUEST_SET_CONFIGURATION: if (!SetupPacket->wIndex.W && !SetupPacket->wLength && !(SetupPacket->bmRequestType.Dir == BMREQUEST_DEVICE_TO_HOST)) { if (SetupPacket->wValue.W == 0 || SetupPacket->wValue.W == PdoExtension->RootHubDescriptors->ConfigDescriptor.bConfigurationValue) { PdoExtension->ConfigurationValue = SetupPacket->wValue.LowByte; RHStatus = RH_STATUS_SUCCESS; } } break; case USB_REQUEST_SET_ADDRESS: if (!SetupPacket->wIndex.W && !SetupPacket->wLength && !(SetupPacket->bmRequestType.Dir)) { PdoExtension->DeviceHandle.DeviceAddress = SetupPacket->wValue.LowByte; RHStatus = RH_STATUS_SUCCESS; break; } break; default: DPRINT1("USBPORT_RootHubStandardCommand: Not supported USB request - %x\n", SetupPacket->bRequest); //USB_REQUEST_CLEAR_FEATURE 0x01 //USB_REQUEST_SET_FEATURE 0x03 //USB_REQUEST_SET_DESCRIPTOR 0x07 //USB_REQUEST_GET_INTERFACE 0x0A //USB_REQUEST_SET_INTERFACE 0x0B //USB_REQUEST_SYNC_FRAME 0x0C break; } return RHStatus; } RHSTATUS NTAPI USBPORT_RootHubEndpoint0(IN PUSBPORT_TRANSFER Transfer) { PDEVICE_OBJECT FdoDevice; ULONG TransferLength; PVOID Buffer; PURB Urb; PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket; UCHAR Type; RHSTATUS RHStatus; DPRINT("USBPORT_RootHubEndpoint0: Transfer - %p\n", Transfer); TransferLength = Transfer->TransferParameters.TransferBufferLength; Urb = Transfer->Urb; FdoDevice = Transfer->Endpoint->FdoDevice; if (TransferLength > 0) Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa; else Buffer = NULL; SetupPacket = (PUSB_DEFAULT_PIPE_SETUP_PACKET)Urb->UrbControlTransfer.SetupPacket; Type = SetupPacket->bmRequestType.Type; if (Type == BMREQUEST_STANDARD) { RHStatus = USBPORT_RootHubStandardCommand(FdoDevice, SetupPacket, Buffer, &TransferLength); } else if (Type == BMREQUEST_CLASS) { RHStatus = USBPORT_RootHubClassCommand(FdoDevice, SetupPacket, Buffer, &TransferLength); } else { return RH_STATUS_UNSUCCESSFUL; } if (RHStatus == RH_STATUS_SUCCESS) Transfer->CompletedTransferLen = TransferLength; return RHStatus; } RHSTATUS NTAPI USBPORT_RootHubSCE(IN PUSBPORT_TRANSFER Transfer) { PUSBPORT_ENDPOINT Endpoint; PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; ULONG TransferLength; USB_PORT_STATUS_AND_CHANGE PortStatus; USB_HUB_STATUS_AND_CHANGE HubStatus; PVOID Buffer; PULONG AddressBitMap; ULONG Port; PURB Urb; RHSTATUS RHStatus = RH_STATUS_NO_CHANGES; PUSB_HUB_DESCRIPTOR HubDescriptor; UCHAR NumberOfPorts; DPRINT("USBPORT_RootHubSCE: Transfer - %p\n", Transfer); Endpoint = Transfer->Endpoint; FdoExtension = Endpoint->FdoDevice->DeviceExtension; PdoExtension = FdoExtension->RootHubPdo->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor; NumberOfPorts = HubDescriptor->bNumberOfPorts; PortStatus.AsUlong32 = 0; HubStatus.AsUlong32 = 0; Urb = Transfer->Urb; TransferLength = Transfer->TransferParameters.TransferBufferLength; if (TransferLength) { Buffer = Urb->UrbControlTransfer.TransferBufferMDL->MappedSystemVa; } else { Buffer = NULL; } /* Check parameters */ if (!Buffer) { /* Not valid parameter */ DPRINT1("USBPORT_RootHubSCE: Error! Buffer is NULL\n"); return RH_STATUS_UNSUCCESSFUL; } if ((TransferLength < (NumberOfPorts / 8 + 1))) { /* Not valid parameters */ DPRINT1("USBPORT_RootHubSCE: Error! TransferLength - %x, NumberOfPorts - %x\n", TransferLength, NumberOfPorts); return RH_STATUS_UNSUCCESSFUL; } RtlZeroMemory(Buffer, TransferLength); AddressBitMap = Buffer; /* Scan all the ports for changes */ for (Port = 1; Port <= NumberOfPorts; Port++) { DPRINT_CORE("USBPORT_RootHubSCE: Port - %p\n", Port); /* Request the port status from miniport */ if (Packet->RH_GetPortStatus(FdoExtension->MiniPortExt, Port, &PortStatus)) { /* Miniport returned an error */ DPRINT1("USBPORT_RootHubSCE: RH_GetPortStatus failed\n"); return RH_STATUS_UNSUCCESSFUL; } if (PortStatus.PortChange.Usb20PortChange.ConnectStatusChange || PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange || PortStatus.PortChange.Usb20PortChange.SuspendChange || PortStatus.PortChange.Usb20PortChange.OverCurrentIndicatorChange || PortStatus.PortChange.Usb20PortChange.ResetChange) { /* At the port status there is a change */ AddressBitMap[Port >> 5] |= 1 << (Port & 0x1F); RHStatus = RH_STATUS_SUCCESS; } } /* Request the hub status from miniport */ if (!Packet->RH_GetHubStatus(FdoExtension->MiniPortExt, &HubStatus)) { if (HubStatus.HubChange.LocalPowerChange == 1 || HubStatus.HubChange.OverCurrentChange == 1) { /* At the hub status there is a change */ AddressBitMap[0] |= 1; RHStatus = RH_STATUS_SUCCESS; } if (RHStatus == RH_STATUS_SUCCESS) { /* Done */ Urb->UrbControlTransfer.TransferBufferLength = TransferLength; return RH_STATUS_SUCCESS; } if (RHStatus == RH_STATUS_NO_CHANGES) { /* No changes. Enable IRQs for miniport root hub */ Packet->RH_EnableIrq(FdoExtension->MiniPortExt); } return RHStatus; } /* Miniport returned an error */ DPRINT1("USBPORT_RootHubSCE: RH_GetHubStatus failed\n"); return RH_STATUS_UNSUCCESSFUL; } VOID NTAPI USBPORT_RootHubEndpointWorker(IN PUSBPORT_ENDPOINT Endpoint) { PDEVICE_OBJECT FdoDevice; PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; PUSBPORT_TRANSFER Transfer; RHSTATUS RHStatus; USBD_STATUS USBDStatus; KIRQL OldIrql; DPRINT_CORE("USBPORT_RootHubEndpointWorker: Endpoint - %p\n", Endpoint); FdoDevice = Endpoint->FdoDevice; FdoExtension = FdoDevice->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql); if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)) { Packet->CheckController(FdoExtension->MiniPortExt); } KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql); KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); Transfer = CONTAINING_RECORD(Endpoint->TransferList.Flink, USBPORT_TRANSFER, TransferLink); if (IsListEmpty(&Endpoint->TransferList) || Endpoint->TransferList.Flink == NULL || !Transfer) { if (Endpoint->StateLast == USBPORT_ENDPOINT_REMOVE) { ExInterlockedInsertTailList(&FdoExtension->EndpointClosedList, &Endpoint->CloseLink, &FdoExtension->EndpointClosedSpinLock); } KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); USBPORT_FlushCancelList(Endpoint); return; } if (Transfer->Flags & (TRANSFER_FLAG_ABORTED | TRANSFER_FLAG_CANCELED)) { RemoveEntryList(&Transfer->TransferLink); InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink); KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); USBPORT_FlushCancelList(Endpoint); return; } KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL) RHStatus = USBPORT_RootHubEndpoint0(Transfer); else RHStatus = USBPORT_RootHubSCE(Transfer); if (RHStatus != RH_STATUS_NO_CHANGES) { if (RHStatus == RH_STATUS_SUCCESS) USBDStatus = USBD_STATUS_SUCCESS; else USBDStatus = USBD_STATUS_STALL_PID; KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql); USBPORT_QueueDoneTransfer(Transfer, USBDStatus); KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql); USBPORT_FlushCancelList(Endpoint); return; } USBPORT_FlushCancelList(Endpoint); } NTSTATUS NTAPI USBPORT_RootHubCreateDevice(IN PDEVICE_OBJECT FdoDevice, IN PDEVICE_OBJECT PdoDevice) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; PUSBPORT_DEVICE_HANDLE DeviceHandle; USBPORT_ROOT_HUB_DATA RootHubData; ULONG NumMaskByte; ULONG DescriptorsLength; PUSBPORT_RH_DESCRIPTORS Descriptors; PUSB_DEVICE_DESCRIPTOR RH_DeviceDescriptor; PUSB_CONFIGURATION_DESCRIPTOR RH_ConfigurationDescriptor; PUSB_INTERFACE_DESCRIPTOR RH_InterfaceDescriptor; PUSB_ENDPOINT_DESCRIPTOR RH_EndPointDescriptor; PUSB_HUB_DESCRIPTOR RH_HubDescriptor; ULONG ix; PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; NTSTATUS Status; DPRINT("USBPORT_RootHubCreateDevice: FdoDevice - %p, PdoDevice - %p\n", FdoDevice, PdoDevice); FdoExtension = FdoDevice->DeviceExtension; PdoExtension = PdoDevice->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; DeviceHandle = &PdoExtension->DeviceHandle; USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle); InitializeListHead(&DeviceHandle->PipeHandleList); DeviceHandle->IsRootHub = TRUE; DeviceHandle->DeviceSpeed = UsbFullSpeed; DeviceHandle->Flags = DEVICE_HANDLE_FLAG_ROOTHUB; RtlZeroMemory(&RootHubData, sizeof(RootHubData)); Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, &RootHubData); ASSERT(RootHubData.NumberOfPorts != 0); NumMaskByte = (RootHubData.NumberOfPorts - 1) / 8 + 1; DescriptorsLength = sizeof(USB_DEVICE_DESCRIPTOR) + sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR) + (sizeof(USB_HUB_DESCRIPTOR) + 2 * NumMaskByte); Descriptors = ExAllocatePoolWithTag(NonPagedPool, DescriptorsLength, USB_PORT_TAG); if (Descriptors) { RtlZeroMemory(Descriptors, DescriptorsLength); PdoExtension->RootHubDescriptors = Descriptors; RH_DeviceDescriptor = &PdoExtension->RootHubDescriptors->DeviceDescriptor; RH_DeviceDescriptor->bLength = sizeof(USB_DEVICE_DESCRIPTOR); RH_DeviceDescriptor->bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE; RH_DeviceDescriptor->bcdUSB = 0x100; RH_DeviceDescriptor->bDeviceClass = USB_DEVICE_CLASS_HUB; RH_DeviceDescriptor->bDeviceSubClass = 0x01; RH_DeviceDescriptor->bDeviceProtocol = 0x00; RH_DeviceDescriptor->bMaxPacketSize0 = 0x08; RH_DeviceDescriptor->idVendor = FdoExtension->VendorID; RH_DeviceDescriptor->idProduct = FdoExtension->DeviceID; RH_DeviceDescriptor->bcdDevice = FdoExtension->RevisionID; RH_DeviceDescriptor->iManufacturer = 0x00; RH_DeviceDescriptor->iProduct = 0x00; RH_DeviceDescriptor->iSerialNumber = 0x00; RH_DeviceDescriptor->bNumConfigurations = 0x01; RH_ConfigurationDescriptor = &PdoExtension->RootHubDescriptors->ConfigDescriptor; RH_ConfigurationDescriptor->bLength = sizeof(USB_CONFIGURATION_DESCRIPTOR); RH_ConfigurationDescriptor->bDescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE; RH_ConfigurationDescriptor->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR); RH_ConfigurationDescriptor->bNumInterfaces = 0x01; RH_ConfigurationDescriptor->bConfigurationValue = 0x01; RH_ConfigurationDescriptor->iConfiguration = 0x00; RH_ConfigurationDescriptor->bmAttributes = USB_CONFIG_SELF_POWERED; RH_ConfigurationDescriptor->MaxPower = 0x00; RH_InterfaceDescriptor = &PdoExtension->RootHubDescriptors->InterfaceDescriptor; RH_InterfaceDescriptor->bLength = sizeof(USB_INTERFACE_DESCRIPTOR); RH_InterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE; RH_InterfaceDescriptor->bInterfaceNumber = 0x00; RH_InterfaceDescriptor->bAlternateSetting = 0x00; RH_InterfaceDescriptor->bNumEndpoints = 0x01; RH_InterfaceDescriptor->bInterfaceClass = USB_DEVICE_CLASS_HUB; RH_InterfaceDescriptor->bInterfaceSubClass = 0x01; RH_InterfaceDescriptor->bInterfaceProtocol = 0x00; RH_InterfaceDescriptor->iInterface = 0x00; RH_EndPointDescriptor = &PdoExtension->RootHubDescriptors->EndPointDescriptor; RH_EndPointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR); RH_EndPointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE; RH_EndPointDescriptor->bEndpointAddress = 0x81; RH_EndPointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT; // SCE endpoint RH_EndPointDescriptor->wMaxPacketSize = 0x0008; RH_EndPointDescriptor->bInterval = 0x0C; // 12 msec RH_HubDescriptor = &PdoExtension->RootHubDescriptors->Descriptor; RH_HubDescriptor->bDescriptorLength = FIELD_OFFSET(USB_HUB_DESCRIPTOR, bRemoveAndPowerMask) + 2 * NumMaskByte; if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_OHCI || Packet->MiniPortVersion == USB_MINIPORT_VERSION_UHCI || Packet->MiniPortVersion == USB_MINIPORT_VERSION_EHCI) { RH_HubDescriptor->bDescriptorType = USB_20_HUB_DESCRIPTOR_TYPE; } else if (Packet->MiniPortVersion == USB_MINIPORT_VERSION_XHCI) { RH_HubDescriptor->bDescriptorType = USB_30_HUB_DESCRIPTOR_TYPE; } else { DPRINT1("USBPORT_RootHubCreateDevice: Unknown MiniPortVersion - %x\n", Packet->MiniPortVersion); DbgBreakPoint(); } RH_HubDescriptor->bNumberOfPorts = RootHubData.NumberOfPorts; RH_HubDescriptor->wHubCharacteristics = RootHubData.HubCharacteristics.AsUSHORT; RH_HubDescriptor->bPowerOnToPowerGood = RootHubData.PowerOnToPowerGood; RH_HubDescriptor->bHubControlCurrent = RootHubData.HubControlCurrent; for (ix = 0; ix < NumMaskByte; ix += 2) { RH_HubDescriptor->bRemoveAndPowerMask[ix] = 0; RH_HubDescriptor->bRemoveAndPowerMask[ix + 1] = -1; } EndpointDescriptor = &DeviceHandle->PipeHandle.EndpointDescriptor; EndpointDescriptor->bLength = sizeof(USB_ENDPOINT_DESCRIPTOR); EndpointDescriptor->bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE; EndpointDescriptor->bEndpointAddress = 0x00; EndpointDescriptor->bmAttributes = USB_ENDPOINT_TYPE_CONTROL; EndpointDescriptor->wMaxPacketSize = 0x0040; EndpointDescriptor->bInterval = 0x00; Status = USBPORT_OpenPipe(FdoDevice, DeviceHandle, &DeviceHandle->PipeHandle, NULL); } else { Status = STATUS_INSUFFICIENT_RESOURCES; } return Status; } ULONG NTAPI USBPORT_InvalidateRootHub(PVOID MiniPortExtension) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PDEVICE_OBJECT FdoDevice; PDEVICE_OBJECT PdoDevice; PUSBPORT_RHDEVICE_EXTENSION PdoExtension; PUSBPORT_ENDPOINT Endpoint = NULL; DPRINT("USBPORT_InvalidateRootHub ... \n"); FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension - sizeof(USBPORT_DEVICE_EXTENSION)); FdoDevice = FdoExtension->CommonExtension.SelfDevice; if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND && FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT && FdoExtension->MiniPortFlags & USBPORT_MPFLAG_SUSPENDED && FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE) { USBPORT_HcQueueWakeDpc(FdoDevice); return 0; } FdoExtension->MiniPortInterface->Packet.RH_DisableIrq(FdoExtension->MiniPortExt); PdoDevice = FdoExtension->RootHubPdo; if (PdoDevice) { PdoExtension = PdoDevice->DeviceExtension; Endpoint = PdoExtension->Endpoint; if (Endpoint) { USBPORT_InvalidateEndpointHandler(FdoDevice, PdoExtension->Endpoint, INVALIDATE_ENDPOINT_WORKER_THREAD); } } return 0; } VOID NTAPI USBPORT_RootHubPowerAndChirpAllCcPorts(IN PDEVICE_OBJECT FdoDevice) { PUSBPORT_DEVICE_EXTENSION FdoExtension; PUSBPORT_REGISTRATION_PACKET Packet; USBPORT_ROOT_HUB_DATA RootHubData; ULONG Port; PDEVICE_RELATIONS CompanionControllersList; PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension; PUSBPORT_REGISTRATION_PACKET CompanionPacket; ULONG CompanionPorts; ULONG NumController; PDEVICE_OBJECT * Entry; ULONG NumPorts; DPRINT("USBPORT_RootHub_PowerAndChirpAllCcPorts: FdoDevice - %p\n", FdoDevice); FdoExtension = FdoDevice->DeviceExtension; Packet = &FdoExtension->MiniPortInterface->Packet; RtlZeroMemory(&RootHubData, sizeof(RootHubData)); Packet->RH_GetRootHubData(FdoExtension->MiniPortExt, &RootHubData); NumPorts = RootHubData.NumberOfPorts; for (Port = 1; Port <= NumPorts; ++Port) { Packet->RH_SetFeaturePortPower(FdoExtension->MiniPortExt, Port); } USBPORT_Wait(FdoDevice, 10); CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice, FALSE, TRUE); if (CompanionControllersList) { Entry = &CompanionControllersList->Objects[0]; for (NumController = 0; NumController < CompanionControllersList->Count; NumController++) { CompanionPacket = &FdoExtension->MiniPortInterface->Packet; CompanionFdoExtension = (*Entry)->DeviceExtension; CompanionPacket->RH_GetRootHubData(CompanionFdoExtension->MiniPortExt, &RootHubData); CompanionPorts = RootHubData.NumberOfPorts; for (Port = 1; Port <= CompanionPorts; ++Port) { CompanionPacket->RH_SetFeaturePortPower(CompanionFdoExtension->MiniPortExt, Port); } ++Entry; } ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG); } USBPORT_Wait(FdoDevice, 100); for (Port = 1; Port <= NumPorts; ++Port) { if (FdoExtension->MiniPortInterface->Version < 200) { break; } InterlockedIncrement((PLONG)&FdoExtension->ChirpRootPortLock); Packet->RH_ChirpRootPort(FdoExtension->MiniPortExt, Port); InterlockedDecrement((PLONG)&FdoExtension->ChirpRootPortLock); } }