diff --git a/reactos/drivers/hid/hidparse/hidparse.c b/reactos/drivers/hid/hidparse/hidparse.c index 6daed49bb56..b3002a25c50 100644 --- a/reactos/drivers/hid/hidparse/hidparse.c +++ b/reactos/drivers/hid/hidparse/hidparse.c @@ -125,6 +125,29 @@ HidP_GetCaps( return HidParser_GetCaps(&Parser, PreparsedData, Capabilities); } +NTSTATUS +TranslateStatusForUpperLayer( + IN HIDPARSER_STATUS Status) +{ + // + // now we are handling only this values, for others just return + // status as it is. + // + switch (Status) + { + case HIDPARSER_STATUS_INSUFFICIENT_RESOURCES: + return STATUS_INSUFFICIENT_RESOURCES; + case HIDPARSER_STATUS_INVALID_REPORT_TYPE: + return HIDP_STATUS_INVALID_REPORT_TYPE; + case HIDPARSER_STATUS_BUFFER_TOO_SMALL: + return STATUS_BUFFER_TOO_SMALL; + case HIDPARSER_STATUS_COLLECTION_NOT_FOUND: + return STATUS_NO_DATA_DETECTED; + default: + return Status; + } +} + NTSTATUS NTAPI HidP_GetCollectionDescription( @@ -134,6 +157,7 @@ HidP_GetCollectionDescription( OUT PHIDP_DEVICE_DESC DeviceDescription) { HID_PARSER Parser; + NTSTATUS Status; // // init parser @@ -143,7 +167,8 @@ HidP_GetCollectionDescription( // // get description; // - return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription); + Status = HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription); + return TranslateStatusForUpperLayer(Status); } HIDAPI diff --git a/reactos/drivers/usb/usbhub/CMakeLists.txt b/reactos/drivers/usb/usbhub/CMakeLists.txt index 2a8224d08cf..db05f9f1cc1 100644 --- a/reactos/drivers/usb/usbhub/CMakeLists.txt +++ b/reactos/drivers/usb/usbhub/CMakeLists.txt @@ -1,5 +1,6 @@ add_definitions(-DDEBUG_MODE) +add_definitions(-DNTDDI_VERSION=0x05020400) include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include) list(APPEND SOURCE diff --git a/reactos/drivers/usb/usbhub/fdo.c b/reactos/drivers/usb/usbhub/fdo.c index 837a3a88bba..13b2081a63e 100644 --- a/reactos/drivers/usb/usbhub/fdo.c +++ b/reactos/drivers/usb/usbhub/fdo.c @@ -569,6 +569,11 @@ QueryInterface( Stack->Parameters.QueryInterface.Interface = Interface; Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; + // + // Initialize the status block before sending the IRP + // + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) @@ -1089,8 +1094,7 @@ DestroyUsbChildDeviceObject( PDEVICE_OBJECT ChildDeviceObject = NULL; ULONG Index = 0; - DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index); - + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for (Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index]) @@ -1111,12 +1115,17 @@ DestroyUsbChildDeviceObject( if (!ChildDeviceObject) { DPRINT1("Removal request for non-existant device!\n"); + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); return STATUS_UNSUCCESSFUL; } + DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index); + /* Remove the device from the table */ HubDeviceExtension->ChildDeviceObject[Index] = NULL; + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + /* Invalidate device relations for the root hub */ IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations); @@ -1147,26 +1156,6 @@ CreateUsbChildDeviceObject( HubInterface = &HubDeviceExtension->HubInterface; RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext; - // - // Find an empty slot in the child device array - // - for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++) - { - if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL) - { - DPRINT("Found unused entry at %d\n", ChildDeviceCount); - break; - } - } - - // - // Check if the limit has been reached for maximum usb devices - // - if (ChildDeviceCount == USB_MAXCHILDREN) - { - DPRINT1("USBHUB: Too many child devices!\n"); - return STATUS_UNSUCCESSFUL; - } while (TRUE) { @@ -1226,10 +1215,6 @@ CreateUsbChildDeviceObject( UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject; UsbChildExtension->PortNumber = PortId; - // copy device interface - RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2)); - - // // Create the UsbDeviceObject // @@ -1244,12 +1229,6 @@ CreateUsbChildDeviceObject( goto Cleanup; } - // copy device interface - RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2)); - - // FIXME replace buscontext - UsbChildExtension->DeviceInterface.BusContext = UsbChildExtension->UsbDeviceHandle; - // // Initialize UsbDevice // @@ -1339,8 +1318,43 @@ CreateUsbChildDeviceObject( goto Cleanup; } + // copy device interface + RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->UsbDInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2)); + UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); + + INITIALIZE_PNP_STATE(UsbChildExtension->Common); + + IoInitializeRemoveLock(&UsbChildExtension->Common.RemoveLock, 'pbuH', 0, 0); + + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); + + // + // Find an empty slot in the child device array + // + for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++) + { + if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL) + { + DPRINT("Found unused entry at %d\n", ChildDeviceCount); + break; + } + } + + // + // Check if the limit has been reached for maximum usb devices + // + if (ChildDeviceCount == USB_MAXCHILDREN) + { + DPRINT1("USBHUB: Too many child devices!\n"); + Status = STATUS_UNSUCCESSFUL; + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext); + goto Cleanup; + } + HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject; HubDeviceExtension->InstanceCount++; + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations); return STATUS_SUCCESS; @@ -1384,16 +1398,20 @@ Cleanup: NTSTATUS USBHUB_FdoQueryBusRelations( IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_RELATIONS RelationsFromTop, OUT PDEVICE_RELATIONS* pDeviceRelations) { PHUB_DEVICE_EXTENSION HubDeviceExtension; PDEVICE_RELATIONS DeviceRelations; ULONG i; + ULONG ChildrenFromTop = 0; ULONG Children = 0; ULONG NeededSize; HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); + // // Count the number of children // @@ -1407,9 +1425,19 @@ USBHUB_FdoQueryBusRelations( Children++; } - NeededSize = sizeof(DEVICE_RELATIONS); - if (Children > 1) - NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT); + if (RelationsFromTop) + { + ChildrenFromTop = RelationsFromTop->Count; + if (!Children) + { + // We have nothing to add + *pDeviceRelations = RelationsFromTop; + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + return STATUS_SUCCESS; + } + } + + NeededSize = sizeof(DEVICE_RELATIONS) + (Children + ChildrenFromTop - 1) * sizeof(PDEVICE_OBJECT); // // Allocate DeviceRelations @@ -1418,9 +1446,22 @@ USBHUB_FdoQueryBusRelations( NeededSize); if (!DeviceRelations) - return STATUS_INSUFFICIENT_RESOURCES; - DeviceRelations->Count = Children; - Children = 0; + { + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + if (!RelationsFromTop) + return STATUS_INSUFFICIENT_RESOURCES; + else + return STATUS_NOT_SUPPORTED; + } + // Copy the objects coming from top + if (ChildrenFromTop) + { + RtlCopyMemory(DeviceRelations->Objects, RelationsFromTop->Objects, + ChildrenFromTop * sizeof(PDEVICE_OBJECT)); + } + + DeviceRelations->Count = Children + ChildrenFromTop; + Children = ChildrenFromTop; // // Fill in return structure @@ -1429,12 +1470,19 @@ USBHUB_FdoQueryBusRelations( { if (HubDeviceExtension->ChildDeviceObject[i]) { + // The PnP Manager removes the reference when appropriate. ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]); HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING; DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i]; } } + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + + // We should do this, because replaced this with our's one + if (RelationsFromTop) + ExFreePool(RelationsFromTop); + ASSERT(Children == DeviceRelations->Count); *pDeviceRelations = DeviceRelations; @@ -1551,7 +1599,8 @@ USBHUB_FdoStartDevice( if (!Urb) { // no memory - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; } // zero urb @@ -1566,8 +1615,7 @@ USBHUB_FdoStartDevice( { // failed to obtain hub pdo DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } // sanity checks @@ -1578,14 +1626,13 @@ USBHUB_FdoStartDevice( RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; // Send the StartDevice to RootHub - Status = ForwardIrpAndWait(RootHubDeviceObject, Irp); + Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp); if (!NT_SUCCESS(Status)) { // failed to start pdo DPRINT1("Failed to start the RootHub PDO\n"); - ExFreePool(Urb); - return Status; + goto cleanup; } // Get the current number of hubs @@ -1596,8 +1643,7 @@ USBHUB_FdoStartDevice( { // failed to get number of hubs DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } // Get the Hub Interface @@ -1611,8 +1657,7 @@ USBHUB_FdoStartDevice( { // failed to get root hub interface DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext; @@ -1628,8 +1673,7 @@ USBHUB_FdoStartDevice( { // failed to get usbdi interface DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } // Get Root Hub Device Handle @@ -1642,8 +1686,7 @@ USBHUB_FdoStartDevice( { // failed DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } // @@ -1687,8 +1730,7 @@ USBHUB_FdoStartDevice( { // failed to get device descriptor of hub DPRINT1("Failed to get HubDeviceDescriptor!\n"); - ExFreePool(Urb); - return Status; + goto cleanup; } // build configuration request @@ -1715,8 +1757,7 @@ USBHUB_FdoStartDevice( { // failed to get configuration descriptor DPRINT1("Failed to get RootHub Configuration with status %x\n", Status); - ExFreePool(Urb); - return Status; + goto cleanup; } // sanity checks @@ -1742,16 +1783,15 @@ USBHUB_FdoStartDevice( { // failed to get hub information DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n"); - ExFreePool(Urb); - return Status; + goto cleanup; } if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts) { // bogus port driver DPRINT1("Failed to retrieve the number of ports\n"); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto cleanup; } DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts); @@ -1782,8 +1822,8 @@ USBHUB_FdoStartDevice( if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor!\n"); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto cleanup; } // sanity checks @@ -1811,8 +1851,8 @@ USBHUB_FdoStartDevice( { // failed to get hub status DPRINT1("Failed to get Hub Status!\n"); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto cleanup; } // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub @@ -1820,6 +1860,13 @@ USBHUB_FdoStartDevice( sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts, USB_HUB_TAG); + if (!HubDeviceExtension->PortStatusChange) + { + DPRINT1("Failed to allocate pool for PortStatusChange!\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + // Get the first Configuration Descriptor Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, &HubDeviceExtension->HubConfigDescriptor, @@ -1828,8 +1875,8 @@ USBHUB_FdoStartDevice( { // failed parse hub descriptor DPRINT1("Failed to parse configuration descriptor\n"); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto cleanup; } // create configuration request @@ -1840,8 +1887,8 @@ USBHUB_FdoStartDevice( { // failed to build urb DPRINT1("Failed to allocate urb\n"); - ExFreePool(Urb); - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; } // send request @@ -1853,9 +1900,7 @@ USBHUB_FdoStartDevice( { // failed to select configuration DPRINT1("Failed to select configuration with %x\n", Status); - ExFreePool(Urb); - ExFreePool(ConfigUrb); - return Status; + goto cleanup; } // store configuration & pipe handle @@ -1863,12 +1908,6 @@ USBHUB_FdoStartDevice( HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); - FDO_QueryInterface(DeviceObject, &HubDeviceExtension->DeviceInterface); - - - // free urb - ExFreePool(ConfigUrb); - // check if function is available if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed) { @@ -1908,8 +1947,7 @@ USBHUB_FdoStartDevice( if (!NT_SUCCESS(Status)) { DPRINT1("Failed to set callback\n"); - ExFreePool(Urb); - return Status; + goto cleanup; } } else @@ -1961,8 +1999,30 @@ USBHUB_FdoStartDevice( // free urb ExFreePool(Urb); + // free ConfigUrb + ExFreePool(ConfigUrb); + // done return Status; + +cleanup: + if (Urb) + ExFreePool(Urb); + + // Dereference interfaces + if (HubDeviceExtension->HubInterface.Size) + HubDeviceExtension->HubInterface.InterfaceDereference(HubDeviceExtension->HubInterface.BusContext); + + if (HubDeviceExtension->UsbDInterface.Size) + HubDeviceExtension->UsbDInterface.InterfaceDereference(HubDeviceExtension->UsbDInterface.BusContext); + + if (HubDeviceExtension->PortStatusChange) + ExFreePool(HubDeviceExtension->PortStatusChange); + + if (ConfigUrb) + ExFreePool(ConfigUrb); + + return Status; } NTSTATUS @@ -1972,17 +2032,31 @@ USBHUB_FdoHandlePnp( { PIO_STACK_LOCATION Stack; NTSTATUS Status = STATUS_SUCCESS; - ULONG_PTR Information = 0; + PDEVICE_OBJECT ChildDeviceObject; PHUB_DEVICE_EXTENSION HubDeviceExtension; + PUSB_BUS_INTERFACE_HUB_V5 HubInterface; + PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + HubInterface = &HubDeviceExtension->HubInterface; Stack = IoGetCurrentIrpStackLocation(Irp); + Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + switch (Stack->MinorFunction) { + int i; + case IRP_MN_START_DEVICE: { + DPRINT("IRP_MN_START_DEVICE\n"); if (USBHUB_IsRootHubFDO(DeviceObject)) { // start root hub fdo @@ -1992,7 +2066,13 @@ USBHUB_FdoHandlePnp( { Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp); } - break; + + SET_NEW_PNP_STATE(HubDeviceExtension->Common, Started); + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); + return Status; } case IRP_MN_QUERY_DEVICE_RELATIONS: @@ -2002,66 +2082,197 @@ USBHUB_FdoHandlePnp( case BusRelations: { PDEVICE_RELATIONS DeviceRelations = NULL; + PDEVICE_RELATIONS RelationsFromTop = (PDEVICE_RELATIONS)Irp->IoStatus.Information; DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); - Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations); + Status = USBHUB_FdoQueryBusRelations(DeviceObject, RelationsFromTop, &DeviceRelations); - Information = (ULONG_PTR)DeviceRelations; + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_NOT_SUPPORTED) + { + // We should process this to not lose relations from top. + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + // We should fail an IRP + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); + return Status; + } + + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; + Irp->IoStatus.Status = Status; break; } case RemovalRelations: { DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); - return ForwardIrpAndForget(DeviceObject, Irp); + break; } default: DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", Stack->Parameters.QueryDeviceRelations.Type); - return ForwardIrpAndForget(DeviceObject, Irp); + break; } break; } - case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: { + // + // We should fail this request, because we're not handling + // IRP_MN_STOP_DEVICE for now.We'll receive this IRP ONLY when + // PnP manager rebalances resources. + // + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NOT_SUPPORTED; + } + case IRP_MN_QUERY_REMOVE_DEVICE: + { + // No action is required from FDO because it have nothing to free. + DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n"); + + SET_NEW_PNP_STATE(HubDeviceExtension->Common, RemovePending); + Irp->IoStatus.Status = STATUS_SUCCESS; - return ForwardIrpAndForget(DeviceObject, Irp); + break; + } + case IRP_MN_CANCEL_REMOVE_DEVICE: + { + DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n"); + + if (HubDeviceExtension->Common.PnPState == RemovePending) + RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension->Common); + + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + } + case IRP_MN_SURPRISE_REMOVAL: + { + // + // We'll receive this IRP on HUB unexpected removal, or on USB + // controller removal from PCI port. Here we should "let know" all + // our children that their parent is removed and on next removal + // they also can be removed. + // + SET_NEW_PNP_STATE(HubDeviceExtension->Common, SurpriseRemovePending); + + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); + + for (i = 0; i < USB_MAXCHILDREN; i++) + { + ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i]; + if (ChildDeviceObject) + { + ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceObjectExtension; + ChildDeviceExtension->ParentDeviceObject = NULL; + } + } + + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + + // This IRP can't be failed + Irp->IoStatus.Status = STATUS_SUCCESS; + break; } case IRP_MN_REMOVE_DEVICE: { + DPRINT("IRP_MN_REMOVE_DEVICE\n"); + + SET_NEW_PNP_STATE(HubDeviceExtension->Common, Deleted); + + IoReleaseRemoveLockAndWait(&HubDeviceExtension->Common.RemoveLock, Irp); + + // + // Here we should remove all child PDOs. At this point all children + // received and returned from IRP_MN_REMOVE so remove synchronization + // isn't needed here + // + + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); + + for (i = 0; i < USB_MAXCHILDREN; i++) + { + ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i]; + if (ChildDeviceObject) + { + PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension; + + SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted); + + // Remove the usb device + if (UsbChildExtension->UsbDeviceHandle) + { + Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0); + ASSERT(Status == STATUS_SUCCESS); + } + + // Free full configuration descriptor + if (UsbChildExtension->FullConfigDesc) + ExFreePool(UsbChildExtension->FullConfigDesc); + + // Free ID buffers + if (UsbChildExtension->usCompatibleIds.Buffer) + ExFreePool(UsbChildExtension->usCompatibleIds.Buffer); + + if (UsbChildExtension->usDeviceId.Buffer) + ExFreePool(UsbChildExtension->usDeviceId.Buffer); + + if (UsbChildExtension->usHardwareIds.Buffer) + ExFreePool(UsbChildExtension->usHardwareIds.Buffer); + + if (UsbChildExtension->usInstanceId.Buffer) + ExFreePool(UsbChildExtension->usInstanceId.Buffer); + + DPRINT("Deleting child PDO\n"); + IoDeleteDevice(DeviceObject); + ChildDeviceObject = NULL; + } + } + + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + Status = ForwardIrpAndForget(DeviceObject, Irp); IoDetachDevice(HubDeviceExtension->LowerDeviceObject); + DPRINT("Deleting FDO 0x%p\n", DeviceObject); IoDeleteDevice(DeviceObject); - return STATUS_SUCCESS; + return Status; } case IRP_MN_QUERY_BUS_INFORMATION: { + // Function drivers and filter drivers do not handle this IRP. DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); break; } case IRP_MN_QUERY_ID: { DPRINT("IRP_MN_QUERY_ID\n"); + // Function drivers and filter drivers do not handle this IRP. break; } case IRP_MN_QUERY_CAPABILITIES: { + // + // If a function or filter driver does not handle this IRP, it + // should pass that down. + // DPRINT("IRP_MN_QUERY_CAPABILITIES\n"); break; } default: { DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction); - return ForwardIrpAndForget(DeviceObject, Irp); + break; } } - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + Status = ForwardIrpAndForget(DeviceObject, Irp); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); return Status; } @@ -2086,6 +2297,25 @@ USBHUB_FdoHandleDeviceControl( // get device extension HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + + // Prevent handling of control requests in remove pending state + if (HubDeviceExtension->Common.PnPState == RemovePending) + { + DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject); + Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); + return STATUS_DEVICE_NOT_CONNECTED; + } + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_INFORMATION) { // is the buffer big enough @@ -2131,6 +2361,7 @@ USBHUB_FdoHandleDeviceControl( // sanity checks ASSERT(NodeConnectionInfo); + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for(Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) @@ -2157,6 +2388,7 @@ USBHUB_FdoHandleDeviceControl( } break; } + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); // done Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION); Status = STATUS_SUCCESS; @@ -2177,6 +2409,7 @@ USBHUB_FdoHandleDeviceControl( // sanity checks ASSERT(NodeKey); + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for(Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) @@ -2216,6 +2449,7 @@ USBHUB_FdoHandleDeviceControl( NodeKey->ActualLength = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); break; } + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); } } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_NAME) @@ -2247,6 +2481,7 @@ USBHUB_FdoHandleDeviceControl( Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); return Status; } diff --git a/reactos/drivers/usb/usbhub/misc.c b/reactos/drivers/usb/usbhub/misc.c index 0800c597cf2..405fde8eba1 100644 --- a/reactos/drivers/usb/usbhub/misc.c +++ b/reactos/drivers/usb/usbhub/misc.c @@ -211,84 +211,3 @@ SubmitRequestToRootHub( return Status; } - -NTSTATUS -NTAPI -FDO_QueryInterfaceCompletionRoutine( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - /* Set event */ - KeSetEvent((PRKEVENT)Context, 0, FALSE); - - /* Completion is done in the HidClassFDO_QueryCapabilities routine */ - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -FDO_QueryInterface( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PUSB_BUS_INTERFACE_USBDI_V2 Interface) -{ - PIRP Irp; - KEVENT Event; - NTSTATUS Status; - PIO_STACK_LOCATION IoStack; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - - /* Get device extension */ - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(HubDeviceExtension->Common.IsFDO); - - /* Init event */ - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - /* Now allocate the irp */ - Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - if (!Irp) - { - /* No memory */ - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Get next stack location */ - IoStack = IoGetNextIrpStackLocation(Irp); - - /* Init stack location */ - IoStack->MajorFunction = IRP_MJ_PNP; - IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE; - IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface; - IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID; - IoStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_2; - IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V2); - - - /* Set completion routine */ - IoSetCompletionRoutine(Irp, - FDO_QueryInterfaceCompletionRoutine, - (PVOID)&Event, - TRUE, - TRUE, - TRUE); - - /* Pnp irps have default completion code */ - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - /* Call lower device */ - Status = IoCallDriver(HubDeviceExtension->LowerDeviceObject, Irp); - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - } - - /* Get status */ - Status = Irp->IoStatus.Status; - - /* Complete request */ - IoFreeIrp(Irp); - - /* Done */ - return Status; -} diff --git a/reactos/drivers/usb/usbhub/pdo.c b/reactos/drivers/usb/usbhub/pdo.c index 6ddc0709f02..daeed55ec25 100644 --- a/reactos/drivers/usb/usbhub/pdo.c +++ b/reactos/drivers/usb/usbhub/pdo.c @@ -146,16 +146,25 @@ IsValidPDO( ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); + + // This can happen when parent device was surprise removed. + if (ChildDeviceExtension->ParentDeviceObject == NULL) + return FALSE; + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for(Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject) { + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); + /* PDO exists */ return TRUE; } } + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); /* invalid pdo */ return FALSE; @@ -190,18 +199,31 @@ USBHUB_PdoHandleInternalDeviceControl( ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - if(!IsValidPDO(DeviceObject)) + Status = IoAcquireRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); + if (!NT_SUCCESS(Status)) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + + if (ChildDeviceExtension->Common.PnPState == SurpriseRemovePending || + ChildDeviceExtension->Common.PnPState == RemovePending || + ChildDeviceExtension->ParentDeviceObject == NULL) + { + // Parent or child device was surprise removed. DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject); Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); return STATUS_DEVICE_NOT_CONNECTED; } + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; + RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; + switch (Stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: @@ -301,6 +323,7 @@ USBHUB_PdoHandleInternalDeviceControl( // Send the request to RootHub // Status = ForwardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL); + IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); return Status; } // @@ -397,6 +420,7 @@ USBHUB_PdoHandleInternalDeviceControl( Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } + IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); return Status; } @@ -421,6 +445,8 @@ USBHUB_PdoStartDevice( IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName); IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE); + SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started); + UNIMPLEMENTED return STATUS_SUCCESS; } @@ -563,15 +589,20 @@ USBHUB_PdoHandlePnp( PIO_STACK_LOCATION Stack; ULONG_PTR Information = 0; PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; - ULONG Index; - ULONG bFound; PDEVICE_RELATIONS DeviceRelation; - PDEVICE_OBJECT ParentDevice; UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation(Irp); MinorFunction = Stack->MinorFunction; + Status = IoAcquireRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + switch (MinorFunction) { case IRP_MN_START_DEVICE: @@ -628,17 +659,20 @@ USBHUB_PdoHandlePnp( } case IRP_MN_QUERY_DEVICE_TEXT: { + DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n"); Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information); break; } case IRP_MN_QUERY_ID: { + DPRINT("IRP_MN_QUERY_ID\n"); Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information); break; } case IRP_MN_QUERY_BUS_INFORMATION: { PPNP_BUS_INFORMATION BusInfo; + DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); RtlCopyMemory(&BusInfo->BusTypeGuid, &GUID_BUS_TYPE_USB, @@ -654,42 +688,58 @@ USBHUB_PdoHandlePnp( { PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension; PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface; - ParentDevice = UsbChildExtension->ParentDeviceObject; DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); - /* remove us from pdo list */ - bFound = FALSE; - for(Index = 0; Index < USB_MAXCHILDREN; Index++) + ASSERT((UsbChildExtension->Common.PnPState == RemovePending) || + (UsbChildExtension->Common.PnPState == SurpriseRemovePending)); + + SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted); + + if (!IsValidPDO(DeviceObject)) { - if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject) + // Parent or child device was surprise removed, freeing resources allocated for child device. + SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted); + + IoReleaseRemoveLockAndWait(&UsbChildExtension->Common.RemoveLock, Irp); + + // Remove the usb device + if (UsbChildExtension->UsbDeviceHandle) { - /* Remove the device */ - Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0); - - /* FIXME handle error */ - ASSERT(Status == STATUS_SUCCESS); - - /* remove us */ - HubDeviceExtension->ChildDeviceObject[Index] = NULL; - bFound = TRUE; - break; + Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0); + ASSERT(Status == STATUS_SUCCESS); } + // Free full configuration descriptor + if (UsbChildExtension->FullConfigDesc) + ExFreePool(UsbChildExtension->FullConfigDesc); + + // Free ID buffers + if (UsbChildExtension->usCompatibleIds.Buffer) + ExFreePool(UsbChildExtension->usCompatibleIds.Buffer); + + if (UsbChildExtension->usDeviceId.Buffer) + ExFreePool(UsbChildExtension->usDeviceId.Buffer); + + if (UsbChildExtension->usHardwareIds.Buffer) + ExFreePool(UsbChildExtension->usHardwareIds.Buffer); + + if (UsbChildExtension->usInstanceId.Buffer) + ExFreePool(UsbChildExtension->usInstanceId.Buffer); + + DPRINT("Deleting child PDO\n"); + IoDeleteDevice(DeviceObject); } + else + { + IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); + } + + // If device is physically presented, we leave its PDO undeleted. /* Complete the IRP */ Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); - /* delete device */ - IoDeleteDevice(DeviceObject); - - if (bFound) - { - /* invalidate device relations */ - IoInvalidateDeviceRelations(ParentDevice, BusRelations); - } - return STATUS_SUCCESS; } case IRP_MN_QUERY_DEVICE_RELATIONS: @@ -699,6 +749,7 @@ USBHUB_PdoHandlePnp( { /* not supported */ Status = Irp->IoStatus.Status; + Information = Irp->IoStatus.Information; break; } @@ -722,13 +773,46 @@ USBHUB_PdoHandlePnp( break; } case IRP_MN_QUERY_STOP_DEVICE: + { + // + // We should fail this request, because we're not handling IRP_MN_STOP_DEVICE for now. + // We'll receive this IRP ONLY when the PnP manager rebalances resources. + // + Status = STATUS_NOT_SUPPORTED; + break; + } case IRP_MN_QUERY_REMOVE_DEVICE: { + // + // Free interface obtained from bottom, according MSDN we should + // check interfaces provided to top, but here we are not checking. + // All checking will be performed in roothub driver's + // IRP_MN_QUERY_REMOVE_DEVICE handler. This will make problems when + // buggy driver is loaded on top of us. But we decided to keep source + // simpler, because in any case buggy driver will prevent removing of + // whole stack. + // + UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext); + + SET_NEW_PNP_STATE(UsbChildExtension->Common, RemovePending); + /* Sure, no problem */ Status = STATUS_SUCCESS; Information = 0; break; } + case IRP_MN_CANCEL_REMOVE_DEVICE: + { + // Check to see have we received query-remove before + if (UsbChildExtension->Common.PnPState == RemovePending) + { + RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension->Common); + UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); + } + + Status = STATUS_SUCCESS; + break; + } case IRP_MN_QUERY_INTERFACE: { DPRINT1("IRP_MN_QUERY_INTERFACE\n"); @@ -736,17 +820,28 @@ USBHUB_PdoHandlePnp( { DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n"); RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size); + UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); Status = STATUS_SUCCESS; break; } // pass irp down IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp); + Status = IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp); + IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); + return Status; } case IRP_MN_SURPRISE_REMOVAL: { DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n"); + + // + // Here we should free all resources and stop all access, lets just set + // the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE + // We can receive this IRP when device is physically connected (on stop/start fail). + // + SET_NEW_PNP_STATE(UsbChildExtension->Common, SurpriseRemovePending); + Status = STATUS_SUCCESS; break; } @@ -758,6 +853,8 @@ USBHUB_PdoHandlePnp( } } + IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); + Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); diff --git a/reactos/drivers/usb/usbhub/usbhub.c b/reactos/drivers/usb/usbhub/usbhub.c index 1596e2109ee..022100ba4b1 100644 --- a/reactos/drivers/usb/usbhub/usbhub.c +++ b/reactos/drivers/usb/usbhub/usbhub.c @@ -62,7 +62,7 @@ USBHUB_AddDevice( PDEVICE_OBJECT DeviceObject; PHUB_DEVICE_EXTENSION HubDeviceExtension; NTSTATUS Status; - DPRINT("USBHUB: AddDevice\n"); + DPRINT("USBHUB: AddDevice (%p)\n", PhysicalDeviceObject); // // Create the Device Object // @@ -86,12 +86,20 @@ USBHUB_AddDevice( HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; RtlZeroMemory(HubDeviceExtension, sizeof(HUB_DEVICE_EXTENSION)); + INITIALIZE_PNP_STATE(HubDeviceExtension->Common); + // // Set this to Fdo // HubDeviceExtension->Common.IsFDO = TRUE; DeviceObject->Flags |= DO_POWER_PAGABLE; + // initialize mutex + KeInitializeGuardedMutex(&HubDeviceExtension->HubMutexLock); + + // initialize remove lock + IoInitializeRemoveLock(&HubDeviceExtension->Common.RemoveLock, 'buH', 0, 0); + // // initialize reset complete event // @@ -158,6 +166,18 @@ USBHUB_DispatchDeviceControl( return USBHUB_IrpStub(DeviceObject, Irp); } +NTSTATUS NTAPI +USBHUB_DispatchSystemControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("Usbhub: DispatchSystemControl\n"); + if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + return USBHUB_IrpStub(DeviceObject, Irp); + else + return USBHUB_IrpStub(DeviceObject, Irp); +} + NTSTATUS NTAPI USBHUB_DispatchInternalDeviceControl( PDEVICE_OBJECT DeviceObject, @@ -188,37 +208,59 @@ USBHUB_DispatchPower( PIRP Irp) { PIO_STACK_LOCATION IoStack; - + PHUB_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; IoStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + + Status = IoAcquireRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + DPRINT1("Power Function %x\n", IoStack->MinorFunction); - if (IoStack->MinorFunction == IRP_MN_SET_POWER) + if (DeviceExtension->Common.IsFDO) { PoStartNextPowerIrp(Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - + IoSkipCurrentIrpStackLocation(Irp); + Status = PoCallDriver(DeviceExtension->LowerDeviceObject, Irp); + IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); + return Status; } - else if (IoStack->MinorFunction == IRP_MN_QUERY_POWER) - { - PoStartNextPowerIrp(Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - else if (IoStack->MinorFunction == IRP_MN_WAIT_WAKE) + switch (IoStack->MinorFunction) { - PoStartNextPowerIrp(Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + case IRP_MN_SET_POWER: + { + DPRINT("IRP_MN_SET_POWER\n"); + break; + } + case IRP_MN_QUERY_POWER: + { + DPRINT("IRP_MN_QUERY_POWER\n"); + break; + } + case IRP_MN_WAIT_WAKE: + { + DPRINT("IRP_MN_WAIT_WAKE\n"); + break; + } + default: + { + DPRINT1("PDO IRP_MJ_POWER / unknown minor function 0x%lx\n", IoStack->MinorFunction); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Irp->IoStatus.Status; + } } PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); return STATUS_SUCCESS; } @@ -245,6 +287,7 @@ DriverEntry( DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBHUB_Close; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBHUB_Cleanup; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBHUB_DispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBHUB_DispatchSystemControl; DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBHUB_DispatchInternalDeviceControl; DriverObject->MajorFunction[IRP_MJ_PNP] = USBHUB_DispatchPnp; DriverObject->MajorFunction[IRP_MJ_POWER] =USBHUB_DispatchPower; diff --git a/reactos/drivers/usb/usbhub/usbhub.h b/reactos/drivers/usb/usbhub/usbhub.h index 1241a813107..6265fb0cb48 100644 --- a/reactos/drivers/usb/usbhub/usbhub.h +++ b/reactos/drivers/usb/usbhub/usbhub.h @@ -39,9 +39,43 @@ typedef struct _WORK_ITEM_DATA PVOID Context; } WORK_ITEM_DATA, *PWORK_ITEM_DATA; + +// +// Definitions for device's PnP state tracking, all this states are described +// in PnP Device States diagram of DDK documentation. +// +typedef enum _DEVICE_PNP_STATE { + + NotStarted = 0, // Not started + Started, // After handling of START_DEVICE IRP + StopPending, // After handling of QUERY_STOP IRP + Stopped, // After handling of STOP_DEVICE IRP + RemovePending, // After handling of QUERY_REMOVE IRP + SurpriseRemovePending, // After handling of SURPRISE_REMOVE IRP + Deleted, // After handling of REMOVE_DEVICE IRP + UnKnown // Unknown state + +} DEVICE_PNP_STATE; + +#define INITIALIZE_PNP_STATE(Data) \ +(Data).PnPState = NotStarted;\ +(Data).PreviousPnPState = NotStarted; + +#define SET_NEW_PNP_STATE(Data, state) \ +(Data).PreviousPnPState = (Data).PnPState;\ +(Data).PnPState = (state); + +#define RESTORE_PREVIOUS_PNP_STATE(Data) \ +(Data).PnPState = (Data).PreviousPnPState; + typedef struct { BOOLEAN IsFDO; + // We'll track device PnP state via this variables + DEVICE_PNP_STATE PnPState; + DEVICE_PNP_STATE PreviousPnPState; + // Remove lock + IO_REMOVE_LOCK RemoveLock; } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; typedef struct _HUB_CHILDDEVICE_EXTENSION @@ -72,6 +106,8 @@ typedef struct _HUB_DEVICE_EXTENSION PDEVICE_OBJECT RootHubPhysicalDeviceObject; PDEVICE_OBJECT RootHubFunctionalDeviceObject; + KGUARDED_MUTEX HubMutexLock; + ULONG NumberOfHubs; KEVENT ResetComplete; @@ -94,7 +130,6 @@ typedef struct _HUB_DEVICE_EXTENSION USBD_CONFIGURATION_HANDLE ConfigurationHandle; USBD_PIPE_HANDLE PipeHandle; PVOID RootHubHandle; - USB_BUS_INTERFACE_USBDI_V2 DeviceInterface; UNICODE_STRING SymbolicLinkName; ULONG InstanceCount; diff --git a/reactos/sdk/lib/drivers/hidparser/context.c b/reactos/sdk/lib/drivers/hidparser/context.c index 3c66b3cd4dd..455d9af8c2a 100644 --- a/reactos/sdk/lib/drivers/hidparser/context.c +++ b/reactos/sdk/lib/drivers/hidparser/context.c @@ -163,7 +163,7 @@ HidParser_StoreCollection( // // store offset // - TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset; + TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset; // // store sub collections @@ -254,7 +254,7 @@ HidParser_SearchReportInCollection( // // get collection // - SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]); + SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]); // // recursively search collection @@ -314,7 +314,7 @@ HidParser_GetCollectionCount( // // get offset to sub collection // - SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]); + SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]); // // count collection for sub nodes diff --git a/reactos/sdk/lib/drivers/hidparser/hidparser.c b/reactos/sdk/lib/drivers/hidparser/hidparser.c index ca6be3c94c2..6e9d4ef6fdd 100644 --- a/reactos/sdk/lib/drivers/hidparser/hidparser.c +++ b/reactos/sdk/lib/drivers/hidparser/hidparser.c @@ -68,7 +68,7 @@ HidParser_GetCollectionDescription( // failed to parse report descriptor // Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus); - return TranslateHidParserStatus(ParserStatus); + return ParserStatus; } // @@ -126,7 +126,9 @@ HidParser_GetCollectionDescription( // // no memory // - return TranslateHidParserStatus(ParserStatus); + Parser->Free(DeviceDescription->CollectionDesc); + Parser->Free(DeviceDescription->ReportIDs); + return ParserStatus; } // @@ -153,6 +155,13 @@ HidParser_GetCollectionDescription( // get collection usage page // ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage); + if (ParserStatus != HIDPARSER_STATUS_SUCCESS) + { + // collection not found + Parser->Free(DeviceDescription->CollectionDesc); + Parser->Free(DeviceDescription->ReportIDs); + return ParserStatus; + } // // windows seems to prepend the report id, regardless if it is required diff --git a/reactos/sdk/lib/drivers/hidparser/parser.c b/reactos/sdk/lib/drivers/hidparser/parser.c index c314a96fe9b..e0208f6f99f 100644 --- a/reactos/sdk/lib/drivers/hidparser/parser.c +++ b/reactos/sdk/lib/drivers/hidparser/parser.c @@ -713,30 +713,6 @@ HidParser_AddMainItem( return HIDPARSER_STATUS_SUCCESS; } -HIDPARSER_STATUS -AllocateParserContext( - IN PHID_PARSER Parser, - OUT PHID_PARSER_CONTEXT *OutParserContext) -{ - PHID_PARSER_CONTEXT ParserContext; - - ParserContext = Parser->Alloc(sizeof(HID_PARSER_CONTEXT)); - if (!ParserContext) - { - // - // failed - // - return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; - } - - // - // store result - // - *OutParserContext = ParserContext; - return HIDPARSER_STATUS_SUCCESS; -} - - HIDPARSER_STATUS HidParser_ParseReportDescriptor( IN PHID_PARSER Parser, @@ -760,12 +736,18 @@ HidParser_ParseReportDescriptor( PMAIN_ITEM_DATA MainItemData; PHID_PARSER_CONTEXT ParserContext; + CurrentOffset = ReportDescriptor; + ReportEnd = ReportDescriptor + ReportLength; + + if (ReportDescriptor >= ReportEnd) + return HIDPARSER_STATUS_COLLECTION_NOT_FOUND; + // // allocate parser // - Status = AllocateParserContext(Parser, &ParserContext); - if (Status != HIDPARSER_STATUS_SUCCESS) - return Status; + ParserContext = Parser->Alloc(sizeof(HID_PARSER_CONTEXT));; + if (!ParserContext) + return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; // @@ -778,6 +760,7 @@ HidParser_ParseReportDescriptor( // // no memory // + Parser->Free(ParserContext); return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; } @@ -792,6 +775,7 @@ HidParser_ParseReportDescriptor( // Parser->Free(ParserContext->LocalItemState.UsageStack); ParserContext->LocalItemState.UsageStack = NULL; + Parser->Free(ParserContext); return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; } @@ -799,8 +783,6 @@ HidParser_ParseReportDescriptor( // start parsing // CurrentCollection = ParserContext->RootCollection; - CurrentOffset = ReportDescriptor; - ReportEnd = ReportDescriptor + ReportLength; do { @@ -1230,8 +1212,7 @@ HidParser_ParseReportDescriptor( // CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX); - - }while(CurrentOffset < ReportEnd); + }while (CurrentOffset < ReportEnd); // diff --git a/reactos/sdk/lib/drivers/libusb/hub_controller.cpp b/reactos/sdk/lib/drivers/libusb/hub_controller.cpp index d3a90a3ef5d..5f0ac072e15 100644 --- a/reactos/sdk/lib/drivers/libusb/hub_controller.cpp +++ b/reactos/sdk/lib/drivers/libusb/hub_controller.cpp @@ -568,7 +568,8 @@ CHubController::HandlePnp( break; } } - Status = STATUS_SUCCESS; + // Here we should leave Status as is. + Status = Irp->IoStatus.Status; break; } case IRP_MN_QUERY_CAPABILITIES: @@ -611,6 +612,14 @@ CHubController::HandlePnp( // handle device interface requests // Status = HandleQueryInterface(IoStack); + + // + // If a bus driver does not export the requested interface, it + // should leave Status as is. + // + if (Status == STATUS_NOT_SUPPORTED) + Status = Irp->IoStatus.Status; + break; } case IRP_MN_REMOVE_DEVICE: @@ -3736,6 +3745,7 @@ CHubController::HandleQueryInterface( InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData; } + InterfaceHub->InterfaceReference(InterfaceHub->BusContext); // // request completed // @@ -3790,6 +3800,7 @@ CHubController::HandleQueryInterface( InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry; } + InterfaceDI->InterfaceReference(InterfaceDI->BusContext); // // request completed //