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
return Status;
}
+ // query bus interface
+ USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject, &FDODeviceExtension->BusInterface);
+
+ // now enumerate the functions
+ Status = USBCCGP_EnumerateFunctions(DeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ // failed to enumerate functions
+ DPRINT1("Failed to enumerate functions with %x\n", Status);
+ return Status;
+ }
+
//
- // FIXME: parse usb interface association descriptor
- // and create PDO for each function
+ // sanity checks
//
- ASSERT(FALSE);
+ ASSERT(FDODeviceExtension->FunctionDescriptorCount);
+ ASSERT(FDODeviceExtension->FunctionDescriptor);
+
+ //
+ // now create the pdo
+ //
+ 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,
{
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;
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+
}