2 * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbccgp/fdo.c
5 * PURPOSE: USB device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
16 FDO_QueryCapabilitiesCompletionRoutine(
17 IN PDEVICE_OBJECT DeviceObject
,
24 KeSetEvent((PRKEVENT
)Context
, 0, FALSE
);
27 // completion is done in the HidClassFDO_QueryCapabilities routine
29 return STATUS_MORE_PROCESSING_REQUIRED
;
33 FDO_QueryCapabilities(
34 IN PDEVICE_OBJECT DeviceObject
,
35 IN OUT PDEVICE_CAPABILITIES Capabilities
)
40 PIO_STACK_LOCATION IoStack
;
41 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
44 // get device extension
46 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
47 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
52 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
55 // now allocte the irp
57 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
63 return STATUS_INSUFFICIENT_RESOURCES
;
67 // get next stack location
69 IoStack
= IoGetNextIrpStackLocation(Irp
);
72 // init stack location
74 IoStack
->MajorFunction
= IRP_MJ_PNP
;
75 IoStack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
76 IoStack
->Parameters
.DeviceCapabilities
.Capabilities
= Capabilities
;
79 // set completion routine
81 IoSetCompletionRoutine(Irp
, FDO_QueryCapabilitiesCompletionRoutine
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
86 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
87 Capabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
88 Capabilities
->Version
= 1; // FIXME hardcoded constant
89 Capabilities
->Address
= MAXULONG
;
90 Capabilities
->UINumber
= MAXULONG
;
93 // pnp irps have default completion code
95 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
100 Status
= IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
101 if (Status
== STATUS_PENDING
)
104 // wait for completion
106 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
112 Status
= Irp
->IoStatus
.Status
;
127 PDEVICE_OBJECT DeviceObject
,
130 ULONG DeviceCount
= 0;
132 PDEVICE_RELATIONS DeviceRelations
;
133 PIO_STACK_LOCATION IoStack
;
134 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
137 // get device extension
139 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
142 // get current irp stack location
144 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
147 // check if relation type is BusRelations
149 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
152 // FDO always only handles bus relations
154 return USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
158 // go through array and count device objects
160 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
162 if (FDODeviceExtension
->ChildPDO
[Index
])
172 // allocate device relations
174 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
) + (DeviceCount
> 1 ? (DeviceCount
-1) * sizeof(PDEVICE_OBJECT
) : 0));
175 if (!DeviceRelations
)
180 return STATUS_INSUFFICIENT_RESOURCES
;
184 // add device objects
186 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
188 if (FDODeviceExtension
->ChildPDO
[Index
])
193 DeviceRelations
->Objects
[DeviceRelations
->Count
] = FDODeviceExtension
->ChildPDO
[Index
];
198 ObReferenceObject(FDODeviceExtension
->ChildPDO
[Index
]);
203 DeviceRelations
->Count
++;
210 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
213 // request completed successfully
215 return STATUS_SUCCESS
;
220 IN PDEVICE_OBJECT DeviceObject
)
223 PDEVICE_OBJECT PDODeviceObject
;
224 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
225 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
229 // get device extension
231 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
232 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
235 // lets create array for the child PDO
237 FDODeviceExtension
->ChildPDO
= AllocateItem(NonPagedPool
, sizeof(PDEVICE_OBJECT
) * FDODeviceExtension
->FunctionDescriptorCount
);
238 if (!FDODeviceExtension
->ChildPDO
)
243 return STATUS_INSUFFICIENT_RESOURCES
;
247 // create pdo for each function
249 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
254 Status
= IoCreateDevice(FDODeviceExtension
->DriverObject
, sizeof(PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_USB
, FILE_AUTOGENERATED_DEVICE_NAME
, FALSE
, &PDODeviceObject
);
255 if (!NT_SUCCESS(Status
))
258 // failed to create device object
260 DPRINT1("IoCreateDevice failed with %x\n", Status
);
267 FDODeviceExtension
->ChildPDO
[Index
] = PDODeviceObject
;
270 // get device extension
272 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
273 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
276 // init device extension
278 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
279 PDODeviceExtension
->FunctionDescriptor
= &FDODeviceExtension
->FunctionDescriptor
[Index
];
280 PDODeviceExtension
->NextDeviceObject
= FDODeviceExtension
->NextDeviceObject
; //DeviceObject; HACK
281 PDODeviceExtension
->FunctionIndex
= Index
;
282 PDODeviceExtension
->InterfaceList
= FDODeviceExtension
->InterfaceList
;
283 PDODeviceExtension
->InterfaceListCount
= FDODeviceExtension
->InterfaceListCount
;
284 PDODeviceExtension
->ConfigurationHandle
= FDODeviceExtension
->ConfigurationHandle
;
285 PDODeviceExtension
->ConfigurationDescriptor
= FDODeviceExtension
->ConfigurationDescriptor
;
286 RtlCopyMemory(&PDODeviceExtension
->Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
287 RtlCopyMemory(&PDODeviceExtension
->DeviceDescriptor
, &FDODeviceExtension
->DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
290 // patch the stack size
292 PDODeviceObject
->StackSize
= DeviceObject
->StackSize
+ 1;
297 PDODeviceObject
->Flags
|= DO_DIRECT_IO
| DO_MAP_IO_BUFFER
;
300 // device is initialized
302 PDODeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
308 return STATUS_SUCCESS
;
313 PDEVICE_OBJECT DeviceObject
,
317 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
320 // get device extension
322 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
326 // first start lower device
328 Status
= USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
330 if (!NT_SUCCESS(Status
))
333 // failed to start lower device
335 DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status
);
340 Status
= USBCCGP_GetDescriptors(DeviceObject
);
341 if (!NT_SUCCESS(Status
))
343 // failed to start lower device
344 DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status
);
349 Status
= FDO_QueryCapabilities(DeviceObject
, &FDODeviceExtension
->Capabilities
);
350 if (!NT_SUCCESS(Status
))
352 // failed to start lower device
353 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
357 // now select the configuration
358 Status
= USBCCGP_SelectConfiguration(DeviceObject
, FDODeviceExtension
);
359 if (!NT_SUCCESS(Status
))
361 // failed to select interface
362 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
366 // query bus interface
367 USBCCGP_QueryInterface(FDODeviceExtension
->NextDeviceObject
, &FDODeviceExtension
->BusInterface
);
369 // now enumerate the functions
370 Status
= USBCCGP_EnumerateFunctions(DeviceObject
);
371 if (!NT_SUCCESS(Status
))
373 // failed to enumerate functions
374 DPRINT1("Failed to enumerate functions with %x\n", Status
);
381 ASSERT(FDODeviceExtension
->FunctionDescriptorCount
);
382 ASSERT(FDODeviceExtension
->FunctionDescriptor
);
383 DumpFunctionDescriptor(FDODeviceExtension
->FunctionDescriptor
, FDODeviceExtension
->FunctionDescriptorCount
);
386 // now create the pdo
388 Status
= FDO_CreateChildPdo(DeviceObject
);
389 if (!NT_SUCCESS(Status
))
394 DPRINT1("FDO_CreateChildPdo failed with %x\n", Status
);
399 // inform pnp manager of new device objects
401 IoInvalidateDeviceRelations(FDODeviceExtension
->PhysicalDeviceObject
, BusRelations
);
406 DPRINT1("[USBCCGP] FDO initialized successfully\n");
412 PDEVICE_OBJECT DeviceObject
,
415 PIO_STACK_LOCATION IoStack
;
417 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
419 // get device extension
420 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
421 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
424 // get stack location
425 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
426 DPRINT1("[USBCCGP] PnP Minor %x\n", IoStack
->MinorFunction
);
427 switch(IoStack
->MinorFunction
)
429 case IRP_MN_START_DEVICE
:
434 Status
= FDO_StartDevice(DeviceObject
, Irp
);
437 case IRP_MN_QUERY_DEVICE_RELATIONS
:
440 // handle device relations
442 Status
= FDO_DeviceRelations(DeviceObject
, Irp
);
445 case IRP_MN_QUERY_CAPABILITIES
:
450 RtlCopyMemory(IoStack
->Parameters
.DeviceCapabilities
.Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
451 Status
= USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
452 if (NT_SUCCESS(Status
))
455 // surprise removal ok
457 IoStack
->Parameters
.DeviceCapabilities
.Capabilities
->SurpriseRemovalOK
= TRUE
;
464 // forward irp to next device object
466 IoSkipCurrentIrpStackLocation(Irp
);
467 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
475 Irp
->IoStatus
.Status
= Status
;
476 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
484 PDEVICE_OBJECT DeviceObject
,
487 PIO_STACK_LOCATION IoStack
;
490 /* get stack location */
491 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
493 switch(IoStack
->MajorFunction
)
496 return FDO_HandlePnp(DeviceObject
, Irp
);
498 DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack
->MajorFunction
);
500 Status
= Irp
->IoStatus
.Status
;
501 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);