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 DPRINT1("[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 DPRINT1("[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
;
487 // forward irp to next device object
489 IoSkipCurrentIrpStackLocation(Irp
);
490 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
498 Irp
->IoStatus
.Status
= Status
;
499 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
504 FDO_HandleResetCyclePort(
505 PDEVICE_OBJECT DeviceObject
,
508 PIO_STACK_LOCATION IoStack
;
510 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
511 PLIST_ENTRY ListHead
, Entry
;
518 // get device extension
520 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
521 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
523 // get stack location
524 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
525 DPRINT1("FDO_HandleResetCyclePort IOCTL %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
527 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
)
530 // use reset port list
532 ListHead
= &FDODeviceExtension
->ResetPortListHead
;
533 ResetActive
= &FDODeviceExtension
->ResetPortActive
;
538 // use cycle port list
540 ListHead
= &FDODeviceExtension
->CyclePortListHead
;
541 ResetActive
= &FDODeviceExtension
->CyclePortActive
;
547 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
552 // insert into pending list
554 InsertTailList(ListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
559 IoMarkIrpPending(Irp
);
560 Status
= STATUS_PENDING
;
565 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
577 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
580 // forward request synchronized
582 USBCCGP_SyncForwardIrp(FDODeviceExtension
->NextDeviceObject
, Irp
);
587 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
590 // mark reset as completed
592 *ResetActive
= FALSE
;
595 // move all requests into temporary list
597 InitializeListHead(&TempList
);
598 while(!IsListEmpty(ListHead
))
600 Entry
= RemoveHeadList(ListHead
);
601 InsertTailList(&TempList
, Entry
);
607 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
610 // complete pending irps
612 while(!IsListEmpty(&TempList
))
614 Entry
= RemoveHeadList(&TempList
);
615 ListIrp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
618 // complete request with status success
620 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
621 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
627 Status
= STATUS_SUCCESS
;
636 FDO_HandleInternalDeviceControl(
637 PDEVICE_OBJECT DeviceObject
,
640 PIO_STACK_LOCATION IoStack
;
642 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
645 // get device extension
647 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
648 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
650 // get stack location
651 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
653 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
||
654 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_CYCLE_PORT
)
657 // handle reset / cycle ports
659 Status
= FDO_HandleResetCyclePort(DeviceObject
, Irp
);
660 DPRINT1("FDO_HandleResetCyclePort Status %x\n", Status
);
661 if (Status
!= STATUS_PENDING
)
666 Irp
->IoStatus
.Status
= Status
;
667 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
673 // forward and forget request
675 IoSkipCurrentIrpStackLocation(Irp
);
676 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
681 PDEVICE_OBJECT DeviceObject
,
684 PIO_STACK_LOCATION IoStack
;
687 /* get stack location */
688 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
690 switch(IoStack
->MajorFunction
)
693 return FDO_HandlePnp(DeviceObject
, Irp
);
694 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
695 return FDO_HandleInternalDeviceControl(DeviceObject
, Irp
);
697 DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack
->MajorFunction
);
699 Status
= Irp
->IoStatus
.Status
;
700 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);