[USBCCGP]
[reactos.git] / drivers / usb / usbccgp / fdo.c
index 7026276..49a7deb 100644 (file)
@@ -127,9 +127,181 @@ FDO_DeviceRelations(
     PDEVICE_OBJECT DeviceObject, 
     PIRP Irp)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG DeviceCount = 0;
+    ULONG Index;
+    PDEVICE_RELATIONS DeviceRelations;
+    PIO_STACK_LOCATION IoStack;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+
+    //
+    // get device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+
+    //
+    // get current irp stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // check if relation type is BusRelations
+    //
+    if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
+    {
+        //
+        // FDO always only handles bus relations
+        //
+        return USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
+    }
+
+    //
+    // go through array and count device objects
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        if (FDODeviceExtension->ChildPDO[Index])
+        {
+            //
+            // child pdo
+            //
+            DeviceCount++;
+        }
+    }
+
+    //
+    // allocate device relations
+    //
+    DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
+    if (!DeviceRelations)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // add device objects
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        if (FDODeviceExtension->ChildPDO[Index])
+        {
+            //
+            // store child pdo
+            //
+            DeviceRelations->Objects[DeviceRelations->Count] = FDODeviceExtension->ChildPDO[Index];
+
+            //
+            // add reference
+            //
+            ObReferenceObject(FDODeviceExtension->ChildPDO[Index]);
+
+            //
+            // increment count
+            //
+            DeviceRelations->Count++;
+        }
+    }
+
+    //
+    // store result
+    //
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+    //
+    // request completed successfully
+    //
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FDO_CreateChildPdo(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS Status;
+    PDEVICE_OBJECT PDODeviceObject;
+    PPDO_DEVICE_EXTENSION PDODeviceExtension;
+    PFDO_DEVICE_EXTENSION FDODeviceExtension;
+    ULONG Index;
+
+    //
+    // get device extension
+    //
+    FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    ASSERT(FDODeviceExtension->Common.IsFDO);
+
+    //
+    // lets create array for the child PDO
+    //
+    FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool, sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
+    if (!FDODeviceExtension->ChildPDO)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // create pdo for each function
+    //
+    for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
+    {
+        //
+        // create the PDO
+        //
+        Status = IoCreateDevice(FDODeviceExtension->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
+        if (!NT_SUCCESS(Status))
+        {
+            //
+            // failed to create device object
+            //
+            DPRINT1("IoCreateDevice failed with %x\n", Status);
+            return Status;
+        }
+
+        //
+        // store in array
+        //
+        FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
+
+        //
+        // get device extension
+        //
+        PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+        RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+
+        //
+        // init device extension
+        //
+        PDODeviceExtension->Common.IsFDO = FALSE;
+        PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
+        PDODeviceExtension->NextDeviceObject = DeviceObject;
+        PDODeviceExtension->FunctionIndex = Index;
+        RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
+
+        //
+        // patch the stack size
+        //
+        PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
+
+        //
+        // set device flags
+        //
+        PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
+
+        //
+        // device is initialized
+        //
+        PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+    }
+
+    //
+    // done
+    //
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -206,13 +378,30 @@ FDO_StartDevice(
     ASSERT(FDODeviceExtension->FunctionDescriptor);
 
     //
-    // FIXME:create PDO for each function
+    // now create the pdo
     //
-    ASSERT(FALSE);
+    Status = FDO_CreateChildPdo(DeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // failed
+        //
+        DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
+        return Status;
+    }
+
+    //
+    // inform pnp manager of new device objects
+    //
+    IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject, BusRelations);
+
+    //
+    // done
+    //
+    DPRINT1("[USBCCGP] FDO initialized successfully\n");
     return Status;
 }
 
-
 NTSTATUS
 FDO_HandlePnp(
     PDEVICE_OBJECT DeviceObject,
@@ -234,11 +423,17 @@ FDO_HandlePnp(
     {
         case IRP_MN_START_DEVICE:
         {
+            //
+            // start the device
+            //
             Status = FDO_StartDevice(DeviceObject, Irp);
             break;
         }
         case IRP_MN_QUERY_DEVICE_RELATIONS:
         {
+            //
+            // handle device relations
+            //
             Status = FDO_DeviceRelations(DeviceObject, Irp);
             break;
         }
@@ -301,6 +496,7 @@ FDO_Dispatch(
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return Status;
     }
+
 }