From a1bb133fae99b7cb113b3ef63bb6ba981e604cbe Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 22 Jan 2012 21:58:06 +0000 Subject: [PATCH] [USB-BRINGUP-TRUNK] - Implement device disconnect indication for usbehci and usbohci - Implement device removal for FDOs and PDOs in usbstor and usbhub svn path=/branches/usb-bringup-trunk/; revision=55080 --- drivers/usb/usbehci_new/hardware.cpp | 27 ++++++++----- drivers/usb/usbhub_new/fdo.c | 58 ++++++++++++++++++++++++++-- drivers/usb/usbhub_new/pdo.c | 20 +++++++--- drivers/usb/usbohci/hardware.cpp | 29 ++++++++------ drivers/usb/usbstor/fdo.c | 33 ++++++++++++++-- drivers/usb/usbstor/pdo.c | 15 +++++-- 6 files changed, 147 insertions(+), 35 deletions(-) diff --git a/drivers/usb/usbehci_new/hardware.cpp b/drivers/usb/usbehci_new/hardware.cpp index 52b764ac100..c62e81b506b 100644 --- a/drivers/usb/usbehci_new/hardware.cpp +++ b/drivers/usb/usbehci_new/hardware.cpp @@ -1131,21 +1131,28 @@ EhciDefferedRoutine( This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED; This->m_PortStatus[i].PortStatus |= USB_PORT_STATUS_CONNECT; This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT; + } + else + { + DPRINT1("Device disconnected on port %d\n", i); // - // is there a status change callback + // update port status flags // - if (This->m_SCECallBack != NULL) - { - // - // queue work item for processing - // - ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); - } + This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_HIGH_SPEED; + This->m_PortStatus[i].PortStatus &= ~USB_PORT_STATUS_CONNECT; + This->m_PortStatus[i].PortChange |= USB_PORT_STATUS_CONNECT; } - else + + // + // is there a status change callback + // + if (This->m_SCECallBack != NULL) { - DPRINT1("Device disconnected on port %d\n", i); + // + // queue work item for processing + // + ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); } // diff --git a/drivers/usb/usbhub_new/fdo.c b/drivers/usb/usbhub_new/fdo.c index 5e54f99a82c..0609c2b5d08 100644 --- a/drivers/usb/usbhub_new/fdo.c +++ b/drivers/usb/usbhub_new/fdo.c @@ -21,6 +21,11 @@ CreateUsbChildDeviceObject( IN LONG PortId, OUT PDEVICE_OBJECT *UsbChildDeviceObject); +NTSTATUS +DestroyUsbChildDeviceObject( + IN PDEVICE_OBJECT UsbHubDeviceObject, + IN LONG PortId); + NTSTATUS SubmitRequestToRootHub( IN PDEVICE_OBJECT RootHubDeviceObject, @@ -304,9 +309,11 @@ DeviceStatusChangeThread( { DPRINT1("Device disconnected from port %d\n", PortId); - // - // FIXME: Remove the device, and deallocate memory - // + Status = DestroyUsbChildDeviceObject(DeviceObject, PortId); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to delete child device object after disconnect\n"); + } } else { @@ -999,6 +1006,51 @@ Cleanup: return Status; } +NTSTATUS +DestroyUsbChildDeviceObject( + IN PDEVICE_OBJECT UsbHubDeviceObject, + IN LONG PortId) +{ + PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension; + PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL; + PDEVICE_OBJECT ChildDeviceObject = NULL; + ULONG Index = 0; + + DPRINT1("Removing device on port %d (Child index: %d)\n", PortId, Index); + + for (Index = 0; Index < USB_MAXCHILDREN; Index++) + { + if (HubDeviceExtension->ChildDeviceObject[Index]) + { + UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension; + + /* Check if it matches the port ID */ + if (UsbChildExtension->PortNumber == PortId) + { + /* We found it */ + ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index]; + break; + } + } + } + + /* Fail the request if the device doesn't exist */ + if (!ChildDeviceObject) + { + DPRINT1("Removal request for non-existant device!\n"); + return STATUS_UNSUCCESSFUL; + } + + /* Remove the device from the table */ + HubDeviceExtension->ChildDeviceObject[Index] = NULL; + + /* Invalidate device relations for the root hub */ + IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations); + + /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */ + return STATUS_SUCCESS; +} + NTSTATUS CreateUsbChildDeviceObject( IN PDEVICE_OBJECT UsbHubDeviceObject, diff --git a/drivers/usb/usbhub_new/pdo.c b/drivers/usb/usbhub_new/pdo.c index 11acf74a26c..3c7646cb55b 100644 --- a/drivers/usb/usbhub_new/pdo.c +++ b/drivers/usb/usbhub_new/pdo.c @@ -582,11 +582,21 @@ USBHUB_PdoHandlePnp( } case IRP_MN_REMOVE_DEVICE: { - // - // FIXME - // - Status = STATUS_SUCCESS; - break; + PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension; + PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface; + + DPRINT1("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); + + /* Remove the device */ + HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0); + + /* Complete the IRP */ + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Delete the device object */ + IoDeleteDevice(DeviceObject); + return STATUS_SUCCESS; } default: { diff --git a/drivers/usb/usbohci/hardware.cpp b/drivers/usb/usbohci/hardware.cpp index 52044d30984..05b91915b81 100644 --- a/drivers/usb/usbohci/hardware.cpp +++ b/drivers/usb/usbohci/hardware.cpp @@ -1447,17 +1447,6 @@ OhciDefferedRoutine( // This->m_PortStatus[Index].PortStatus |= USB_PORT_STATUS_LOW_SPEED; } - - // - // is there a status change callback - // - if (This->m_SCECallBack != NULL) - { - // - // queue work item for processing - // - ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); - } } else { @@ -1465,6 +1454,24 @@ OhciDefferedRoutine( // device disconnected // DPRINT1("Device disconnected at Port %x\n", Index); + + // + // update port status flags + // + This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_LOW_SPEED; + This->m_PortStatus[Index].PortStatus &= ~USB_PORT_STATUS_CONNECT; + This->m_PortStatus[Index].PortChange |= USB_PORT_STATUS_CONNECT; + } + + // + // is there a status change callback + // + if (This->m_SCECallBack != NULL) + { + // + // queue work item for processing + // + ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); } } } diff --git a/drivers/usb/usbstor/fdo.c b/drivers/usb/usbstor/fdo.c index 2bca8ac7824..08efa25ce5f 100644 --- a/drivers/usb/usbstor/fdo.c +++ b/drivers/usb/usbstor/fdo.c @@ -118,6 +118,31 @@ USBSTOR_FdoHandleDeviceRelations( return STATUS_SUCCESS; } +NTSTATUS +USBSTOR_FdoHandleRemoveDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PFDO_DEVICE_EXTENSION DeviceExtension, + IN OUT PIRP Irp) +{ + NTSTATUS Status; + + DPRINT1("Handling FDO removal\n"); + + /* We don't need to request removal of our children here */ + + /* Send the IRP down the stack */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); + + /* Detach from the device stack */ + /* IoDetachDevice(DeviceExtension->LowerDeviceObject); */ //This crashes for some reason during unload + + /* Delete the device object */ + IoDeleteDevice(DeviceObject); + + return Status; +} + NTSTATUS USBSTOR_FdoHandleStartDevice( IN PDEVICE_OBJECT DeviceObject, @@ -302,9 +327,11 @@ USBSTOR_FdoHandlePnp( Status = STATUS_NOT_SUPPORTED; break; case IRP_MN_REMOVE_DEVICE: - DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n"); - Status = STATUS_NOT_SUPPORTED; - break; + { + DPRINT1("IRP_MN_REMOVE_DEVICE\n"); + + return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp); + } case IRP_MN_QUERY_CAPABILITIES: { // diff --git a/drivers/usb/usbstor/pdo.c b/drivers/usb/usbstor/pdo.c index ecb6ab8962b..4a50a00609f 100644 --- a/drivers/usb/usbstor/pdo.c +++ b/drivers/usb/usbstor/pdo.c @@ -842,9 +842,18 @@ USBSTOR_PdoHandlePnp( break; } case IRP_MN_REMOVE_DEVICE: - DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_REMOVE_DEVICE unimplemented\n"); - Status = STATUS_SUCCESS; - break; + { + DPRINT1("IRP_MN_REMOVE_DEVICE\n"); + + /* Complete the IRP */ + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Delete the device object */ + IoDeleteDevice(DeviceObject); + + return STATUS_SUCCESS; + } case IRP_MN_QUERY_CAPABILITIES: { // -- 2.17.1