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)
19 FDO_QueryCapabilitiesCompletionRoutine(
20 IN PDEVICE_OBJECT DeviceObject
,
25 KeSetEvent((PRKEVENT
)Context
, 0, FALSE
);
27 /* Completion is done in the HidClassFDO_QueryCapabilities routine */
28 return STATUS_MORE_PROCESSING_REQUIRED
;
32 FDO_QueryCapabilities(
33 IN PDEVICE_OBJECT DeviceObject
,
34 IN OUT PDEVICE_CAPABILITIES Capabilities
)
39 PIO_STACK_LOCATION IoStack
;
40 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
42 /* Get device extension */
43 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
44 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
47 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
49 /* Now allocate the irp */
50 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
54 return STATUS_INSUFFICIENT_RESOURCES
;
57 /* Get next stack location */
58 IoStack
= IoGetNextIrpStackLocation(Irp
);
60 /* Init stack location */
61 IoStack
->MajorFunction
= IRP_MJ_PNP
;
62 IoStack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
63 IoStack
->Parameters
.DeviceCapabilities
.Capabilities
= Capabilities
;
65 /* Set completion routine */
66 IoSetCompletionRoutine(Irp
,
67 FDO_QueryCapabilitiesCompletionRoutine
,
73 /* Init capabilities */
74 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
75 Capabilities
->Size
= sizeof(DEVICE_CAPABILITIES
);
76 Capabilities
->Version
= 1; // FIXME hardcoded constant
77 Capabilities
->Address
= MAXULONG
;
78 Capabilities
->UINumber
= MAXULONG
;
80 /* Pnp irps have default completion code */
81 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
83 /* Call lower device */
84 Status
= IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
85 if (Status
== STATUS_PENDING
)
87 /* Wait for completion */
88 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
92 Status
= Irp
->IoStatus
.Status
;
94 /* Complete request */
103 PDEVICE_OBJECT DeviceObject
,
106 ULONG DeviceCount
= 0;
108 PDEVICE_RELATIONS DeviceRelations
;
109 PIO_STACK_LOCATION IoStack
;
110 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
112 /* Get device extension */
113 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
115 /* Get current irp stack location */
116 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
118 /* Check if relation type is BusRelations */
119 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
121 /* FDO always only handles bus relations */
122 return STATUS_SUCCESS
;
125 /* Go through array and count device objects */
126 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
128 if (FDODeviceExtension
->ChildPDO
[Index
])
135 /* Allocate device relations */
136 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(PagedPool
,
137 sizeof(DEVICE_RELATIONS
) + (DeviceCount
> 1 ? (DeviceCount
-1) * sizeof(PDEVICE_OBJECT
) : 0));
138 if (!DeviceRelations
)
141 return STATUS_INSUFFICIENT_RESOURCES
;
144 /* Add device objects */
145 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
147 if (FDODeviceExtension
->ChildPDO
[Index
])
149 /* Store child pdo */
150 DeviceRelations
->Objects
[DeviceRelations
->Count
] = FDODeviceExtension
->ChildPDO
[Index
];
153 ObReferenceObject(FDODeviceExtension
->ChildPDO
[Index
]);
155 /* Increment count */
156 DeviceRelations
->Count
++;
161 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
162 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
164 /* Request completed successfully */
165 return STATUS_SUCCESS
;
170 IN PDEVICE_OBJECT DeviceObject
)
173 PDEVICE_OBJECT PDODeviceObject
;
174 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
175 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
178 /* Get device extension */
179 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
180 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
182 /* Lets create array for the child PDO */
183 FDODeviceExtension
->ChildPDO
= AllocateItem(NonPagedPool
,
184 sizeof(PDEVICE_OBJECT
) * FDODeviceExtension
->FunctionDescriptorCount
);
185 if (!FDODeviceExtension
->ChildPDO
)
188 return STATUS_INSUFFICIENT_RESOURCES
;
191 /* Create pdo for each function */
192 for(Index
= 0; Index
< FDODeviceExtension
->FunctionDescriptorCount
; Index
++)
195 Status
= IoCreateDevice(FDODeviceExtension
->DriverObject
,
196 sizeof(PDO_DEVICE_EXTENSION
),
199 FILE_AUTOGENERATED_DEVICE_NAME
,
202 if (!NT_SUCCESS(Status
))
204 /* Failed to create device object */
205 DPRINT1("IoCreateDevice failed with %x\n", Status
);
210 FDODeviceExtension
->ChildPDO
[Index
] = PDODeviceObject
;
212 /* Get device extension */
213 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
214 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
216 /* Init device extension */
217 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
218 PDODeviceExtension
->FunctionDescriptor
= &FDODeviceExtension
->FunctionDescriptor
[Index
];
219 PDODeviceExtension
->NextDeviceObject
= DeviceObject
;
220 PDODeviceExtension
->FunctionIndex
= Index
;
221 PDODeviceExtension
->FDODeviceExtension
= FDODeviceExtension
;
222 PDODeviceExtension
->InterfaceList
= FDODeviceExtension
->InterfaceList
;
223 PDODeviceExtension
->InterfaceListCount
= FDODeviceExtension
->InterfaceListCount
;
224 PDODeviceExtension
->ConfigurationHandle
= FDODeviceExtension
->ConfigurationHandle
;
225 PDODeviceExtension
->ConfigurationDescriptor
= FDODeviceExtension
->ConfigurationDescriptor
;
226 RtlCopyMemory(&PDODeviceExtension
->Capabilities
, &FDODeviceExtension
->Capabilities
, sizeof(DEVICE_CAPABILITIES
));
227 RtlCopyMemory(&PDODeviceExtension
->DeviceDescriptor
, FDODeviceExtension
->DeviceDescriptor
, sizeof(USB_DEVICE_DESCRIPTOR
));
229 /* Patch the stack size */
230 PDODeviceObject
->StackSize
= DeviceObject
->StackSize
+ 1;
232 /* Set device flags */
233 PDODeviceObject
->Flags
|= DO_DIRECT_IO
| DO_MAP_IO_BUFFER
;
235 /* Device is initialized */
236 PDODeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
240 return STATUS_SUCCESS
;
245 PDEVICE_OBJECT DeviceObject
,
249 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
251 /* Get device extension */
252 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
253 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
255 /* First start lower device */
256 if (IoForwardIrpSynchronously(FDODeviceExtension
->NextDeviceObject
, Irp
))
258 Status
= Irp
->IoStatus
.Status
;
262 Status
= STATUS_UNSUCCESSFUL
;
265 if (!NT_SUCCESS(Status
))
267 /* Failed to start lower device */
268 DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status
);
272 /* Get descriptors */
273 Status
= USBCCGP_GetDescriptors(DeviceObject
);
274 if (!NT_SUCCESS(Status
))
276 /* Failed to start lower device */
277 DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status
);
281 /* Get capabilities */
282 Status
= FDO_QueryCapabilities(DeviceObject
,
283 &FDODeviceExtension
->Capabilities
);
284 if (!NT_SUCCESS(Status
))
286 /* Failed to start lower device */
287 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
291 /* Now select the configuration */
292 Status
= USBCCGP_SelectConfiguration(DeviceObject
, FDODeviceExtension
);
293 if (!NT_SUCCESS(Status
))
295 /* Failed to select interface */
296 DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status
);
300 /* Query bus interface */
301 USBCCGP_QueryInterface(FDODeviceExtension
->NextDeviceObject
,
302 &FDODeviceExtension
->BusInterface
);
304 /* Now enumerate the functions */
305 Status
= USBCCGP_EnumerateFunctions(DeviceObject
);
306 if (!NT_SUCCESS(Status
))
308 /* Failed to enumerate functions */
309 DPRINT1("Failed to enumerate functions with %x\n", Status
);
314 ASSERT(FDODeviceExtension
->FunctionDescriptorCount
);
315 ASSERT(FDODeviceExtension
->FunctionDescriptor
);
316 DumpFunctionDescriptor(FDODeviceExtension
->FunctionDescriptor
,
317 FDODeviceExtension
->FunctionDescriptorCount
);
319 /* Now create the pdo */
320 Status
= FDO_CreateChildPdo(DeviceObject
);
321 if (!NT_SUCCESS(Status
))
324 DPRINT1("FDO_CreateChildPdo failed with %x\n", Status
);
328 /* Inform pnp manager of new device objects */
329 IoInvalidateDeviceRelations(FDODeviceExtension
->PhysicalDeviceObject
,
333 DPRINT("[USBCCGP] FDO initialized successfully\n");
338 FDO_CloseConfiguration(
339 IN PDEVICE_OBJECT DeviceObject
)
343 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
345 /* Get device extension */
346 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
347 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
349 /* Nothing to do if we're not configured */
350 if (FDODeviceExtension
->ConfigurationDescriptor
== NULL
||
351 FDODeviceExtension
->InterfaceList
== NULL
)
353 return STATUS_SUCCESS
;
356 /* Now allocate the urb */
357 Urb
= USBD_CreateConfigurationRequestEx(FDODeviceExtension
->ConfigurationDescriptor
,
358 FDODeviceExtension
->InterfaceList
);
362 return STATUS_INSUFFICIENT_RESOURCES
;
365 /* Clear configuration descriptor to make it an unconfigure request */
366 Urb
->UrbSelectConfiguration
.ConfigurationDescriptor
= NULL
;
369 Status
= USBCCGP_SyncUrbRequest(FDODeviceExtension
->NextDeviceObject
, Urb
);
370 if (!NT_SUCCESS(Status
))
372 /* Failed to set configuration */
373 DPRINT1("USBCCGP_SyncUrbRequest failed to unconfigure device\n", Status
);
383 PDEVICE_OBJECT DeviceObject
,
386 PIO_STACK_LOCATION IoStack
;
388 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
390 /* Get device extension */
391 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
392 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
395 /* Get stack location */
396 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
397 DPRINT("[USBCCGP] PnP Minor %x\n", IoStack
->MinorFunction
);
398 switch(IoStack
->MinorFunction
)
400 case IRP_MN_REMOVE_DEVICE
:
402 // Unconfigure device */
403 DPRINT1("[USBCCGP] FDO IRP_MN_REMOVE\n");
404 FDO_CloseConfiguration(DeviceObject
);
406 /* Send the IRP down the stack */
407 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
408 IoSkipCurrentIrpStackLocation(Irp
);
409 Status
= IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
411 /* Detach from the device stack */
412 IoDetachDevice(FDODeviceExtension
->NextDeviceObject
);
414 /* Delete the device object */
415 IoDeleteDevice(DeviceObject
);
417 /* Request completed */
420 case IRP_MN_START_DEVICE
:
422 /* Start the device */
423 Status
= FDO_StartDevice(DeviceObject
, Irp
);
426 case IRP_MN_QUERY_DEVICE_RELATIONS
:
428 /* Handle device relations */
429 Status
= FDO_DeviceRelations(DeviceObject
, Irp
);
430 if (!NT_SUCCESS(Status
))
435 /* Forward irp to next device object */
436 IoSkipCurrentIrpStackLocation(Irp
);
437 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
439 case IRP_MN_QUERY_CAPABILITIES
:
441 /* Copy capabilities */
442 RtlCopyMemory(IoStack
->Parameters
.DeviceCapabilities
.Capabilities
,
443 &FDODeviceExtension
->Capabilities
,
444 sizeof(DEVICE_CAPABILITIES
));
445 Status
= STATUS_UNSUCCESSFUL
;
447 if (IoForwardIrpSynchronously(FDODeviceExtension
->NextDeviceObject
, Irp
))
449 Status
= Irp
->IoStatus
.Status
;
450 if (NT_SUCCESS(Status
))
452 IoStack
->Parameters
.DeviceCapabilities
.Capabilities
->SurpriseRemovalOK
= TRUE
;
457 case IRP_MN_QUERY_REMOVE_DEVICE
:
458 case IRP_MN_QUERY_STOP_DEVICE
:
461 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
463 /* Forward irp to next device object */
464 IoSkipCurrentIrpStackLocation(Irp
);
465 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
469 /* Forward irp to next device object */
470 IoSkipCurrentIrpStackLocation(Irp
);
471 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
476 /* Complete request */
477 Irp
->IoStatus
.Status
= Status
;
478 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
483 FDO_HandleResetCyclePort(
484 PDEVICE_OBJECT DeviceObject
,
487 PIO_STACK_LOCATION IoStack
;
489 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
490 PLIST_ENTRY ListHead
, Entry
;
496 /* Get device extension */
497 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
498 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
500 /* Get stack location */
501 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
502 DPRINT("FDO_HandleResetCyclePort IOCTL %x\n", IoStack
->Parameters
.DeviceIoControl
.IoControlCode
);
504 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
)
506 /* Use reset port list */
507 ListHead
= &FDODeviceExtension
->ResetPortListHead
;
508 ResetActive
= &FDODeviceExtension
->ResetPortActive
;
512 /* Use cycle port list */
513 ListHead
= &FDODeviceExtension
->CyclePortListHead
;
514 ResetActive
= &FDODeviceExtension
->CyclePortActive
;
518 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
522 /* Insert into pending list */
523 InsertTailList(ListHead
, &Irp
->Tail
.Overlay
.ListEntry
);
525 /* Mark irp pending */
526 IoMarkIrpPending(Irp
);
527 Status
= STATUS_PENDING
;
530 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
534 /* Mark reset active */
538 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
540 /* Forward request synchronized */
541 NT_VERIFY(IoForwardIrpSynchronously(FDODeviceExtension
->NextDeviceObject
, Irp
));
544 KeAcquireSpinLock(&FDODeviceExtension
->Lock
, &OldLevel
);
546 /* Mark reset as completed */
547 *ResetActive
= FALSE
;
549 /* Move all requests into temporary list */
550 InitializeListHead(&TempList
);
551 while(!IsListEmpty(ListHead
))
553 Entry
= RemoveHeadList(ListHead
);
554 InsertTailList(&TempList
, Entry
);
558 KeReleaseSpinLock(&FDODeviceExtension
->Lock
, OldLevel
);
560 /* Complete pending irps */
561 while(!IsListEmpty(&TempList
))
563 Entry
= RemoveHeadList(&TempList
);
564 ListIrp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
566 /* Complete request with status success */
567 ListIrp
->IoStatus
.Status
= STATUS_SUCCESS
;
568 IoCompleteRequest(ListIrp
, IO_NO_INCREMENT
);
572 Status
= STATUS_SUCCESS
;
581 FDO_HandleInternalDeviceControl(
582 PDEVICE_OBJECT DeviceObject
,
585 PIO_STACK_LOCATION IoStack
;
587 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
589 /* Get device extension */
590 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
591 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
593 /* Get stack location */
594 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
596 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_RESET_PORT
||
597 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_INTERNAL_USB_CYCLE_PORT
)
599 /* Handle reset / cycle ports */
600 Status
= FDO_HandleResetCyclePort(DeviceObject
, Irp
);
601 DPRINT("FDO_HandleResetCyclePort Status %x\n", Status
);
602 if (Status
!= STATUS_PENDING
)
604 /* Complete request */
605 Irp
->IoStatus
.Status
= Status
;
606 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
611 /* Forward and forget request */
612 IoSkipCurrentIrpStackLocation(Irp
);
613 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
617 FDO_HandleSystemControl(
618 PDEVICE_OBJECT DeviceObject
,
621 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
623 /* Get device extension */
624 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
625 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
627 /* Forward and forget request */
628 IoSkipCurrentIrpStackLocation(Irp
);
629 return IoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
634 PDEVICE_OBJECT DeviceObject
,
637 PIO_STACK_LOCATION IoStack
;
639 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
641 /* Get device extension */
642 FDODeviceExtension
= DeviceObject
->DeviceExtension
;
643 ASSERT(FDODeviceExtension
->Common
.IsFDO
);
645 /* Get stack location */
646 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
648 switch(IoStack
->MajorFunction
)
651 return FDO_HandlePnp(DeviceObject
, Irp
);
652 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
653 return FDO_HandleInternalDeviceControl(DeviceObject
, Irp
);
655 PoStartNextPowerIrp(Irp
);
656 IoSkipCurrentIrpStackLocation(Irp
);
657 return PoCallDriver(FDODeviceExtension
->NextDeviceObject
, Irp
);
658 case IRP_MJ_SYSTEM_CONTROL
:
659 return FDO_HandleSystemControl(DeviceObject
, Irp
);
661 DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack
->MajorFunction
);
663 Status
= Irp
->IoStatus
.Status
;
664 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);