[USB-BRINGUP-TRUNK]
authorCameron Gutman <aicommander@gmail.com>
Sun, 22 Jan 2012 21:58:06 +0000 (21:58 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sun, 22 Jan 2012 21:58:06 +0000 (21:58 +0000)
- 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
drivers/usb/usbhub_new/fdo.c
drivers/usb/usbhub_new/pdo.c
drivers/usb/usbohci/hardware.cpp
drivers/usb/usbstor/fdo.c
drivers/usb/usbstor/pdo.c

index 52b764a..c62e81b 100644 (file)
@@ -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);
                 }
 
                 //
index 5e54f99..0609c2b 100644 (file)
@@ -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,
index 11acf74..3c7646c 100644 (file)
@@ -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:
         {
index 52044d3..05b9191 100644 (file)
@@ -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);
                 }
             }
         }
index 2bca8ac..08efa25 100644 (file)
@@ -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:
        {
            //
index ecb6ab8..4a50a00 100644 (file)
@@ -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:
        {
            //