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
= DeviceObject
;
281 PDODeviceExtension
->FunctionIndex
= Index
;
282 PDODeviceExtension
->FDODeviceExtension
= FDODeviceExtension
;
283 PDODeviceExtension
->InterfaceList
= FDODeviceExtension
->InterfaceList
;
284 PDODeviceExtension
->InterfaceListCount
= FDODeviceExtension
->InterfaceListCount
;
285 PDODeviceExtension
->ConfigurationHandle
= FDODeviceExtension
->ConfigurationHandle
;
286 PDODeviceExtension
->ConfigurationDescriptor
= FDODeviceExtension
->ConfigurationDescriptor
;
287 RtlCopyMemory(&PDODeviceExtension
->Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
288 RtlCopyMemory(&PDODeviceExtension
->DeviceDescriptor
, &FDODeviceExtension
->DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
291 // patch the stack size
293 PDODeviceObject
->StackSize
= DeviceObject
->StackSize
+ 1;
298 PDODeviceObject
->Flags
|= DO_DIRECT_IO
| DO_MAP_IO_BUFFER
;
301 // device is initialized
303 PDODeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
309 return STATUS_SUCCESS
;
314 PDEVICE_OBJECT DeviceObject
,
318 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
321 // get device extension
323 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
324 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
327 // first start lower device
329 Status
= USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
331 if (!NT_SUCCESS(Status
))
334 // failed to start lower device
336 DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status
);
341 Status
= USBCCGP_GetDescriptors(DeviceObject
);
342 if (!NT_SUCCESS(Status
))
344 // failed to start lower device
345 DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status
);
350 Status
= FDO_QueryCapabilities(DeviceObject
, &FDODeviceExtension
->Capabilities
);
351 if (!NT_SUCCESS(Status
))
353 // failed to start lower device
354 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
358 // now select the configuration
359 Status
= USBCCGP_SelectConfiguration(DeviceObject
, FDODeviceExtension
);
360 if (!NT_SUCCESS(Status
))
362 // failed to select interface
363 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
367 // query bus interface
368 USBCCGP_QueryInterface(FDODeviceExtension
->NextDeviceObject
, &FDODeviceExtension
->BusInterface
);
370 // now enumerate the functions
371 Status
= USBCCGP_EnumerateFunctions(DeviceObject
);
372 if (!NT_SUCCESS(Status
))
374 // failed to enumerate functions
375 DPRINT1("Failed to enumerate functions with %x\n", Status
);
382 ASSERT(FDODeviceExtension
->FunctionDescriptorCount
);
383 ASSERT(FDODeviceExtension
->FunctionDescriptor
);
384 DumpFunctionDescriptor(FDODeviceExtension
->FunctionDescriptor
, FDODeviceExtension
->FunctionDescriptorCount
);
387 // now create the pdo
389 Status
= FDO_CreateChildPdo(DeviceObject
);
390 if (!NT_SUCCESS(Status
))
395 DPRINT1("FDO_CreateChildPdo failed with %x\n", Status
);
400 // inform pnp manager of new device objects
402 IoInvalidateDeviceRelations(FDODeviceExtension
->PhysicalDeviceObject
, BusRelations
);
407 DPRINT("[USBCCGP] FDO initialized successfully\n");
413 PDEVICE_OBJECT DeviceObject
,
416 PIO_STACK_LOCATION IoStack
;
418 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
420 // get device extension
421 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
422 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
425 // get stack location
426 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
427 DPRINT("[USBCCGP] PnP Minor %x\n", IoStack
->MinorFunction
);
428 switch(IoStack
->MinorFunction
)
430 case IRP_MN_REMOVE_DEVICE
:
432 /* Send the IRP down the stack */
433 Status
= USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
434 if (NT_SUCCESS(Status
))
437 // Detach from the device stack
439 IoDetachDevice(FDODeviceExtension
->NextDeviceObject
);
442 // Delete the device object
444 IoDeleteDevice(DeviceObject
);
452 case IRP_MN_START_DEVICE
:
457 Status
= FDO_StartDevice(DeviceObject
, Irp
);
460 case IRP_MN_QUERY_DEVICE_RELATIONS
:
463 // handle device relations
465 Status
= FDO_DeviceRelations(DeviceObject
, Irp
);
468 case IRP_MN_QUERY_CAPABILITIES
:
473 RtlCopyMemory(IoStack
->Parameters
.DeviceCapabilities
.Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
474 Status
= USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
475 if (NT_SUCCESS(Status
))
478 // surprise removal ok
480 IoStack
->Parameters
.DeviceCapabilities
.Capabilities
->SurpriseRemovalOK
= TRUE
;
484 case IRP_MN_QUERY_REMOVE_DEVICE
:
485 case IRP_MN_QUERY_STOP_DEVICE
:
490 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
493 // forward irp to next device object
495 IoSkipCurrentIrpStackLocation(Irp
);
496 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
501 // forward irp to next device object
503 IoSkipCurrentIrpStackLocation(Irp
);
504 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
512 Irp
->IoStatus
.Status
= Status
;
513 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
518 FDO_HandleResetCyclePort(
519 PDEVICE_OBJECT DeviceObject
,
522 PIO_STACK_LOCATION IoStack
;
524 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
525 PLIST_ENTRY ListHead
, Entry
;
532 // get device extension
534 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
535 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
537 // get stack location
538 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
539 DPRINT("FDO_HandleResetCyclePort IOCTL %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
541 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
)
544 // use reset port list
546 ListHead
= &FDODeviceExtension
->ResetPortListHead
;
547 ResetActive
= &FDODeviceExtension
->ResetPortActive
;
552 // use cycle port list
554 ListHead
= &FDODeviceExtension
->CyclePortListHead
;
555 ResetActive
= &FDODeviceExtension
->CyclePortActive
;
561 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
566 // insert into pending list
568 InsertTailList(ListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
573 IoMarkIrpPending(Irp
);
574 Status
= STATUS_PENDING
;
579 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
591 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
594 // forward request synchronized
596 USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
601 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
604 // mark reset as completed
606 *ResetActive
= FALSE
;
609 // move all requests into temporary list
611 InitializeListHead(&TempList
);
612 while(!IsListEmpty(ListHead
))
614 Entry
= RemoveHeadList(ListHead
);
615 InsertTailList(&TempList
, Entry
);
621 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
624 // complete pending irps
626 while(!IsListEmpty(&TempList
))
628 Entry
= RemoveHeadList(&TempList
);
629 ListIrp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
632 // complete request with status success
634 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
635 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
641 Status
= STATUS_SUCCESS
;
650 FDO_HandleInternalDeviceControl(
651 PDEVICE_OBJECT DeviceObject
,
654 PIO_STACK_LOCATION IoStack
;
656 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
659 // get device extension
661 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
662 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
664 // get stack location
665 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
667 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
||
668 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_CYCLE_PORT
)
671 // handle reset / cycle ports
673 Status
= FDO_HandleResetCyclePort(DeviceObject
, Irp
);
674 DPRINT("FDO_HandleResetCyclePort Status %x\n", Status
);
675 if (Status
!= STATUS_PENDING
)
680 Irp
->IoStatus
.Status
= Status
;
681 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
687 // forward and forget request
689 IoSkipCurrentIrpStackLocation(Irp
);
690 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
695 PDEVICE_OBJECT DeviceObject
,
698 PIO_STACK_LOCATION IoStack
;
701 /* get stack location */
702 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
704 switch(IoStack
->MajorFunction
)
707 return FDO_HandlePnp(DeviceObject
, Irp
);
708 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
709 return FDO_HandleInternalDeviceControl(DeviceObject
, Irp
);
711 DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack
->MajorFunction
);
713 Status
= Irp
->IoStatus
.Status
;
714 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);