Author: akhaldi Date: Fri Jan 27 11:09:36 2017 New Revision: 73605 URL: http://svn.reactos.org/svn/reactos?rev=73605&view=rev Log: [HIDPARSE][HIDPARSER][LIBUSB][USBHUB] Merge USB stack improvements by Vardan Mikayelyan in GSoC.
Modified: trunk/reactos/ (props changed) trunk/reactos/drivers/hid/hidparse/ (props changed) trunk/reactos/drivers/hid/hidparse/hidparse.c trunk/reactos/drivers/usb/usbhub/ (props changed) trunk/reactos/drivers/usb/usbhub/CMakeLists.txt trunk/reactos/drivers/usb/usbhub/fdo.c trunk/reactos/drivers/usb/usbhub/misc.c trunk/reactos/drivers/usb/usbhub/pdo.c trunk/reactos/drivers/usb/usbhub/usbhub.c trunk/reactos/drivers/usb/usbhub/usbhub.h trunk/reactos/sdk/lib/drivers/hidparser/context.c trunk/reactos/sdk/lib/drivers/hidparser/hidparser.c trunk/reactos/sdk/lib/drivers/hidparser/parser.c trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp (contents, props changed) Propchange: trunk/reactos/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Jan 27 11:09:36 2017 @@ -2,7 +2,7 @@ /branches/GSoC_2011/GSoC_TcpIpDriver:51550 /branches/GSoC_2011/TcpIpDriver:51551-53074,53076-53119 /branches/GSoC_2016/AHCI:71203-73603 -/branches/GSoC_2016/USB:72366,72376 +/branches/GSoC_2016/USB:72365-73604 /branches/GSoC_Network:51545-51546 /branches/cmake-bringup:50484,50693,50719,51544-52564 /branches/colins-printing-for-freedom/reactos:67543-68405,68407-68414,68417-70595 Propchange: trunk/reactos/drivers/hid/hidparse/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Jan 27 11:09:36 2017 @@ -1,6 +1,7 @@ /branches/GSoC_2011/GSoC_Network/drivers/hid/hidparse:51548 /branches/GSoC_2011/GSoC_TcpIpDriver/drivers/hid/hidparse:51550 /branches/GSoC_2011/TcpIpDriver/drivers/hid/hidparse:51551-53074,53076-53119 +/branches/GSoC_2016/USB/drivers/hid/hidparse:72365-73604 /branches/GSoC_Network/drivers/hid/hidparse:51545-51546 /branches/cmake-bringup/drivers/hid/hidparse:50484,50693,50719,51544-52564 /branches/condrv_restructure/drivers/hid/hidparse:63104-64101 Modified: trunk/reactos/drivers/hid/hidparse/hidparse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/hid/hidparse/hidparse.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/hid/hidparse/hidparse.c [iso-8859-1] (original) +++ trunk/reactos/drivers/hid/hidparse/hidparse.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -126,6 +126,29 @@ } 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( IN PHIDP_REPORT_DESCRIPTOR ReportDesc, @@ -134,6 +157,7 @@ OUT PHIDP_DEVICE_DESC DeviceDescription) { HID_PARSER Parser; + NTSTATUS Status; // // init parser @@ -143,7 +167,8 @@ // // get description; // - return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription); + Status = HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription); + return TranslateStatusForUpperLayer(Status); } HIDAPI Propchange: trunk/reactos/drivers/usb/usbhub/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Jan 27 11:09:36 2017 @@ -4,7 +4,7 @@ /branches/GSoC_2011/GSoC_TcpIpDriver/drivers/usb/usbhub_new:51550 /branches/GSoC_2011/TcpIpDriver/drivers/usb/usbhub:51551-53074,53076-53119 /branches/GSoC_2011/TcpIpDriver/drivers/usb/usbhub_new:51551-53074,53076-53119 -/branches/GSoC_2016/USB/drivers/usb/usbhub:72366,72376 +/branches/GSoC_2016/USB/drivers/usb/usbhub:72365-73604 /branches/GSoC_Network/drivers/usb/usbhub:51545-51546 /branches/GSoC_Network/drivers/usb/usbhub_new:51545-51546 /branches/cmake-bringup/drivers/usb/usbhub:50484,50693,50719,51544-52564 Modified: trunk/reactos/drivers/usb/usbhub/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/CMakeLists.txt?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/CMakeLists.txt [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -1,5 +1,6 @@ add_definitions(-DDEBUG_MODE) +add_definitions(-DNTDDI_VERSION=0x05020400) include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include) list(APPEND SOURCE Modified: trunk/reactos/drivers/usb/usbhub/fdo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/fdo.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/fdo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/fdo.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -568,6 +568,11 @@ Stack->Parameters.QueryInterface.Version = Version; 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); @@ -1089,8 +1094,7 @@ 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,11 +1115,16 @@ 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 @@ 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 @@ UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject; UsbChildExtension->PortNumber = PortId; - // copy device interface - RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2)); - - // // Create the UsbDeviceObject // @@ -1243,12 +1228,6 @@ DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status); 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 @@ 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 @@ 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 @@ 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 @@ 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,11 +1470,18 @@ { 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 @@ if (!Urb) { // no memory - return STATUS_INSUFFICIENT_RESOURCES; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; } // zero urb @@ -1566,8 +1615,7 @@ { // 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 @@ 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 @@ { // 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 @@ { // 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 @@ { // 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 @@ { // 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 @@ { // 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 @@ { // 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 @@ { // 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 @@ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor!\n"); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; + Status = STATUS_UNSUCCESSFUL; + goto cleanup; } // sanity checks @@ -1811,14 +1851,21 @@ { // 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 HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool, 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, @@ -1828,8 +1875,8 @@ { // 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 @@ { // 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 @@ { // 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 @@ 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 @@ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to set callback\n"); - ExFreePool(Urb); - return Status; + goto cleanup; } } else @@ -1961,7 +1999,29 @@ // 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; } @@ -1972,17 +2032,31 @@ { 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 @@ { 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 @@ 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); - - Information = (ULONG_PTR)DeviceRelations; + Status = USBHUB_FdoQueryBusRelations(DeviceObject, RelationsFromTop, &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_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: - case IRP_MN_QUERY_STOP_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); - } - } - - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + } + } + + Status = ForwardIrpAndForget(DeviceObject, Irp); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); return Status; } @@ -2086,6 +2297,25 @@ // 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 @@ // sanity checks ASSERT(NodeConnectionInfo); + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for(Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) @@ -2157,6 +2388,7 @@ } break; } + KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); // done Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION); Status = STATUS_SUCCESS; @@ -2177,6 +2409,7 @@ // sanity checks ASSERT(NodeKey); + KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); for(Index = 0; Index < USB_MAXCHILDREN; Index++) { if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) @@ -2216,6 +2449,7 @@ 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 @@ Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); return Status; } Modified: trunk/reactos/drivers/usb/usbhub/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/misc.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/misc.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/misc.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -211,84 +211,3 @@ 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; -} Modified: trunk/reactos/drivers/usb/usbhub/pdo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/pdo.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/pdo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/pdo.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -146,16 +146,25 @@ 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,17 +199,30 @@ 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) { @@ -301,6 +323,7 @@ // 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 @@ Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } + IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); return Status; } @@ -420,6 +444,8 @@ // 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,14 +589,19 @@ 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) { @@ -628,17 +659,20 @@ } 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 @@ { 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++) - { - if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject) + ASSERT((UsbChildExtension->Common.PnPState == RemovePending) || + (UsbChildExtension->Common.PnPState == SurpriseRemovePending)); + + SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted); + + if (!IsValidPDO(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 @@ { /* not supported */ Status = Irp->IoStatus.Status; + Information = Irp->IoStatus.Information; break; } @@ -722,13 +773,46 @@ 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 @@ { 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; } @@ -757,6 +852,8 @@ Status = Irp->IoStatus.Status; } } + + IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; Modified: trunk/reactos/drivers/usb/usbhub/usbhub.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/usbhub.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/usbhub.c [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/usbhub.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -62,7 +62,7 @@ PDEVICE_OBJECT DeviceObject; PHUB_DEVICE_EXTENSION HubDeviceExtension; NTSTATUS Status; - DPRINT("USBHUB: AddDevice\n"); + DPRINT("USBHUB: AddDevice (%p)\n", PhysicalDeviceObject); // // Create the Device Object // @@ -86,11 +86,19 @@ 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 @@ -159,6 +167,18 @@ } 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, PIRP Irp) @@ -188,37 +208,59 @@ 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; - - } - 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) - { - 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; + } + + switch (IoStack->MinorFunction) + { + 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 @@ 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; Modified: trunk/reactos/drivers/usb/usbhub/usbhub.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbhub/usbhub.h?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/drivers/usb/usbhub/usbhub.h [iso-8859-1] (original) +++ trunk/reactos/drivers/usb/usbhub/usbhub.h [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -39,9 +39,43 @@ 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 @@ PDEVICE_OBJECT RootHubPhysicalDeviceObject; PDEVICE_OBJECT RootHubFunctionalDeviceObject; + KGUARDED_MUTEX HubMutexLock; + ULONG NumberOfHubs; KEVENT ResetComplete; @@ -94,7 +130,6 @@ USBD_CONFIGURATION_HANDLE ConfigurationHandle; USBD_PIPE_HANDLE PipeHandle; PVOID RootHubHandle; - USB_BUS_INTERFACE_USBDI_V2 DeviceInterface; UNICODE_STRING SymbolicLinkName; ULONG InstanceCount; Modified: trunk/reactos/sdk/lib/drivers/hidparser/context.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/hidparser/context.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/sdk/lib/drivers/hidparser/context.c [iso-8859-1] (original) +++ trunk/reactos/sdk/lib/drivers/hidparser/context.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -163,7 +163,7 @@ // // store offset // - TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset; + TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset; // // store sub collections @@ -254,7 +254,7 @@ // // 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 @@ // // 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 Modified: trunk/reactos/sdk/lib/drivers/hidparser/hidparser.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/hidparser/hidparser.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/sdk/lib/drivers/hidparser/hidparser.c [iso-8859-1] (original) +++ trunk/reactos/sdk/lib/drivers/hidparser/hidparser.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -68,7 +68,7 @@ // 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 @@ // // no memory // - return TranslateHidParserStatus(ParserStatus); + Parser->Free(DeviceDescription->CollectionDesc); + Parser->Free(DeviceDescription->ReportIDs); + return ParserStatus; } // @@ -153,6 +155,13 @@ // 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 Modified: trunk/reactos/sdk/lib/drivers/hidparser/parser.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/hidparser/parser.c?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/sdk/lib/drivers/hidparser/parser.c [iso-8859-1] (original) +++ trunk/reactos/sdk/lib/drivers/hidparser/parser.c [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -712,30 +712,6 @@ // 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( @@ -760,12 +736,18 @@ 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 @@ // // no memory // + Parser->Free(ParserContext); return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; } @@ -792,6 +775,7 @@ // Parser->Free(ParserContext->LocalItemState.UsageStack); ParserContext->LocalItemState.UsageStack = NULL; + Parser->Free(ParserContext); return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES; } @@ -799,8 +783,6 @@ // start parsing // CurrentCollection = ParserContext->RootCollection; - CurrentOffset = ReportDescriptor; - ReportEnd = ReportDescriptor + ReportLength; do { @@ -1230,8 +1212,7 @@ // CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX); - - }while(CurrentOffset < ReportEnd); + }while (CurrentOffset < ReportEnd); // Modified: trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp?rev=73605&r1=73604&r2=73605&view=diff ============================================================================== --- trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp [iso-8859-1] (original) +++ trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp [iso-8859-1] Fri Jan 27 11:09:36 2017 @@ -568,7 +568,8 @@ 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 @@ // 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 @@ InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData; } + InterfaceHub->InterfaceReference(InterfaceHub->BusContext); // // request completed // @@ -3790,6 +3800,7 @@ InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry; } + InterfaceDI->InterfaceReference(InterfaceDI->BusContext); // // request completed // Propchange: trunk/reactos/sdk/lib/drivers/libusb/hub_controller.cpp ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Jan 27 11:09:36 2017 @@ -4,6 +4,7 @@ /branches/GSoC_2011/GSoC_TcpIpDriver/drivers/usb/usbehci_new/hub_controller.cpp:51550 /branches/GSoC_2011/TcpIpDriver/drivers/usb/usbehci/hub_controller.cpp:51551-53074,53076-53119 /branches/GSoC_2011/TcpIpDriver/drivers/usb/usbehci_new/hub_controller.cpp:51551-53074,53076-53119 +/branches/GSoC_2016/USB/sdk/lib/drivers/libusb/hub_controller.cpp:72365-73604 /branches/GSoC_Network/drivers/usb/usbehci/hub_controller.cpp:51545-51546 /branches/GSoC_Network/drivers/usb/usbehci_new/hub_controller.cpp:51545-51546 /branches/cmake-bringup/drivers/usb/usbehci/hub_controller.cpp:50484,50693,50719,51544-52564