[USBHUB_NEW]
[reactos.git] / drivers / usb / usbhub_new / fdo.c
index 5e54f99..89bc706 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
             {
@@ -428,6 +435,7 @@ DeviceStatusChangeThread(
 }
 
 NTSTATUS
+NTAPI
 StatusChangeEndpointCompletion(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp,
@@ -457,7 +465,7 @@ StatusChangeEndpointCompletion(
     }
     WorkItemData->Context = RealDeviceObject;
     DPRINT1("Initialize work item\n");
-    ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)DeviceStatusChangeThread, (PVOID)WorkItemData);
+    ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
 
     //
     // Queue the work item to handle initializing the device
@@ -550,7 +558,7 @@ QueryStatusChangeEndpoint(
     // Set the completion routine for when device is connected to root hub
     //
     IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp,
-                           (PIO_COMPLETION_ROUTINE) StatusChangeEndpointCompletion,
+                           StatusChangeEndpointCompletion,
                            DeviceObject,
                            TRUE,
                            TRUE,
@@ -999,6 +1007,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,
@@ -1282,6 +1335,7 @@ USBHUB_FdoQueryBusRelations(
 }
 
 VOID
+NTAPI
 RootHubInitCallbackFunction(
     PVOID Context)
 {
@@ -1634,7 +1688,7 @@ USBHUB_FdoHandlePnp(
             {
                 Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext,
                                                                                   DeviceObject,
-                                                                                  (PRH_INIT_CALLBACK)RootHubInitCallbackFunction);
+                                                                                  RootHubInitCallbackFunction);
                 if (!NT_SUCCESS(Status))
                 {
                     DPRINT1("Failed to set callback\n");