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/usbehci/pdo.c
5 * PURPOSE: USB EHCI device driver.
19 /* Lifted from Linux with slight changes */
20 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR
[] =
23 USB_DEVICE_DESCRIPTOR_TYPE
, /* bDescriptorType; Device */
24 0x00, 0x20, /* bcdUSB; v1.1 */
25 USB_DEVICE_CLASS_HUB
, /* bDeviceClass; HUB_CLASSCODE */
26 0x01, /* bDeviceSubClass; */
27 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
28 0x08, /* bMaxPacketSize0; 8 Bytes */
29 /* Fill Vendor and Product in when init root hub */
30 0x00, 0x00, /* idVendor; */
31 0x00, 0x00, /* idProduct; */
32 0x00, 0x00, /* bcdDevice */
33 0x00, /* iManufacturer; */
35 0x00, /* iSerialNumber; */
36 0x01 /* bNumConfigurations; */
40 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR
[] =
42 /* one configuration */
44 0x02, /* bDescriptorType; Configuration */
45 0x19, 0x00, /* wTotalLength; */
46 0x01, /* bNumInterfaces; (1) */
47 0x23, /* bConfigurationValue; */
48 0x00, /* iConfiguration; */
49 0x40, /* bmAttributes;
57 0x09, /* bLength: Interface; */
58 0x04, /* bDescriptorType; Interface */
59 0x00, /* bInterfaceNumber; */
60 0x00, /* bAlternateSetting; */
61 0x01, /* bNumEndpoints; */
62 0x09, /* bInterfaceClass; HUB_CLASSCODE */
63 0x01, /* bInterfaceSubClass; */
64 0x00, /* bInterfaceProtocol: */
65 0x00, /* iInterface; */
67 /* one endpoint (status change endpoint) */
69 0x05, /* bDescriptorType; Endpoint */
70 0x81, /* bEndpointAddress; IN Endpoint 1 */
71 0x03, /* bmAttributes; Interrupt */
72 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
73 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
76 /* FIXME: Do something better */
78 UrbWorkerThread(PVOID Context
)
80 PPDO_DEVICE_EXTENSION PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)Context
;
82 while (PdoDeviceExtension
->HaltUrbHandling
== FALSE
)
84 CompletePendingURBRequest(PdoDeviceExtension
);
85 KeStallExecutionProcessor(10);
87 DPRINT1("Thread terminated\n");
90 /* FIXME: Do something better */
91 PVOID
InternalCreateUsbDevice(UCHAR DeviceNumber
, ULONG Port
, PUSB_DEVICE Parent
, BOOLEAN Hub
)
93 PUSB_DEVICE UsbDevicePointer
= NULL
;
94 UsbDevicePointer
= ExAllocatePool(NonPagedPool
, sizeof(USB_DEVICE
));
95 if (!UsbDevicePointer
)
97 DPRINT1("Out of memory\n");
101 if ((Hub
) && (!Parent
))
103 DPRINT1("This is the root hub\n");
106 UsbDevicePointer
->Address
= DeviceNumber
;
107 UsbDevicePointer
->Port
= Port
;
108 UsbDevicePointer
->ParentDevice
= Parent
;
110 UsbDevicePointer
->IsHub
= Hub
;
112 return UsbDevicePointer
;
116 PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
118 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
119 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
120 PIO_STACK_LOCATION Stack
= NULL
;
121 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
122 ULONG_PTR Information
= 0;
124 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
125 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
) PdoDeviceExtension
->ControllerFdo
->DeviceExtension
;
127 ASSERT(PdoDeviceExtension
->Common
.IsFdo
== FALSE
);
129 Stack
= IoGetCurrentIrpStackLocation(Irp
);
131 switch(Stack
->Parameters
.DeviceIoControl
.IoControlCode
)
133 case IOCTL_INTERNAL_USB_SUBMIT_URB
:
137 Urb
= (PURB
) Stack
->Parameters
.Others
.Argument1
;
138 DPRINT("Header Length %d\n", Urb
->UrbHeader
.Length
);
139 DPRINT("Header Function %d\n", Urb
->UrbHeader
.Function
);
141 /* Queue all request for now, kernel thread will complete them */
142 QueueURBRequest(PdoDeviceExtension
, Irp
);
144 IoMarkIrpPending(Irp
);
145 Status
= STATUS_PENDING
;
148 case IOCTL_INTERNAL_USB_CYCLE_PORT
:
150 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
153 case IOCTL_INTERNAL_USB_ENABLE_PORT
:
155 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
158 case IOCTL_INTERNAL_USB_GET_BUS_INFO
:
160 DPRINT1("IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
163 case IOCTL_INTERNAL_USB_GET_BUSGUID_INFO
:
165 DPRINT1("IOCTL_INTERNAL_USB_GET_BUSGUID_INFO\n");
168 case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
:
170 DPRINT1("IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n");
173 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
:
175 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE
);
176 if (Stack
->Parameters
.Others
.Argument1
)
178 /* Return the root hubs devicehandle */
179 *(PVOID
*)Stack
->Parameters
.Others
.Argument1
= (PVOID
)PdoDeviceExtension
->UsbDevices
[0];
182 Status
= STATUS_INVALID_DEVICE_REQUEST
;
185 case IOCTL_INTERNAL_USB_GET_HUB_COUNT
:
187 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT
);
188 if (Stack
->Parameters
.Others
.Argument1
)
190 /* FIXME: Determine the number of hubs between the usb device and root hub */
191 /* For now return 1, the root hub */
192 *(PVOID
*)Stack
->Parameters
.Others
.Argument1
= (PVOID
)1;
196 case IOCTL_INTERNAL_USB_GET_HUB_NAME
:
198 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_NAME\n");
201 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO
:
203 DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
206 case IOCTL_INTERNAL_USB_GET_PORT_STATUS
:
208 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
211 case IOCTL_INTERNAL_USB_RESET_PORT
:
213 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
216 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
:
218 DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
220 if (Stack
->Parameters
.Others
.Argument1
)
221 *(PVOID
*)Stack
->Parameters
.Others
.Argument1
= FdoDeviceExtension
->Pdo
;
222 if (Stack
->Parameters
.Others
.Argument2
)
223 *(PVOID
*)Stack
->Parameters
.Others
.Argument2
= IoGetAttachedDevice(FdoDeviceExtension
->DeviceObject
);
226 Status
= STATUS_SUCCESS
;
229 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
:
231 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
236 DPRINT1("Unhandled IoControlCode %x\n", Stack
->Parameters
.DeviceIoControl
.IoControlCode
);
241 Irp
->IoStatus
.Information
= Information
;
243 if (Status
!= STATUS_PENDING
)
244 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
250 PdoQueryId(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, ULONG_PTR
* Information
)
255 UNICODE_STRING SourceString
;
256 UNICODE_STRING String
;
259 IdType
= IoGetCurrentIrpStackLocation(Irp
)->Parameters
.QueryId
.IdType
;
263 case BusQueryDeviceID
:
265 RtlInitUnicodeString(&SourceString
, L
"USB\\ROOT_HUB20");
268 case BusQueryHardwareIDs
:
270 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
271 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
272 Index
+= swprintf(&Buffer
[Index
], L
"USB\\ROOT_HUB20") + 1;
274 Buffer
[Index
] = UNICODE_NULL
;
275 SourceString
.Length
= SourceString
.MaximumLength
= Index
* sizeof(WCHAR
);
276 SourceString
.Buffer
= Buffer
;
279 case BusQueryCompatibleIDs
:
282 return STATUS_SUCCESS
;
284 case BusQueryInstanceID
:
286 return STATUS_SUCCESS
;
290 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
291 return STATUS_NOT_SUPPORTED
;
295 Status
= DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
299 *Information
= (ULONG_PTR
)String
.Buffer
;
304 PdoQueryDeviceRelations(PDEVICE_OBJECT DeviceObject
, PDEVICE_RELATIONS
* pDeviceRelations
)
306 PDEVICE_RELATIONS DeviceRelations
;
308 DeviceRelations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
309 if (!DeviceRelations
)
310 return STATUS_INSUFFICIENT_RESOURCES
;
312 DeviceRelations
->Count
= 1;
313 DeviceRelations
->Objects
[0] = DeviceObject
;
314 ObReferenceObject(DeviceObject
);
316 *pDeviceRelations
= DeviceRelations
;
317 return STATUS_SUCCESS
;
322 IN PDEVICE_OBJECT DeviceObject
,
326 PIO_STACK_LOCATION Stack
;
327 ULONG_PTR Information
= Irp
->IoStatus
.Information
;
328 NTSTATUS Status
= Irp
->IoStatus
.Status
;
330 Stack
= IoGetCurrentIrpStackLocation(Irp
);
331 MinorFunction
= Stack
->MinorFunction
;
333 switch (MinorFunction
)
335 case IRP_MN_QUERY_REMOVE_DEVICE
:
336 case IRP_MN_REMOVE_DEVICE
:
337 case IRP_MN_CANCEL_REMOVE_DEVICE
:
338 case IRP_MN_STOP_DEVICE
:
339 case IRP_MN_QUERY_STOP_DEVICE
:
340 case IRP_MN_CANCEL_STOP_DEVICE
:
341 case IRP_MN_QUERY_DEVICE_TEXT
:
342 case IRP_MN_SURPRISE_REMOVAL
:
343 case IRP_MN_QUERY_RESOURCES
:
344 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
345 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
347 Status
= STATUS_SUCCESS
;
351 case IRP_MN_START_DEVICE
:
353 PUSB_DEVICE RootHubDevice
;
354 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
355 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
356 UNICODE_STRING InterfaceSymLinkName
;
359 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
360 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)PdoDeviceExtension
->ControllerFdo
->DeviceExtension
;
362 /* Create the root hub */
363 RootHubDevice
= InternalCreateUsbDevice(1, 0, NULL
, TRUE
);
365 for (i
= 0; i
< 8; i
++)
367 PdoDeviceExtension
->Ports
[i
].PortStatus
= USB_PORT_STATUS_ENABLE
;
368 PdoDeviceExtension
->Ports
[i
].PortChange
= 0;
371 RtlCopyMemory(&RootHubDevice
->DeviceDescriptor
,
372 ROOTHUB2_DEVICE_DESCRIPTOR
,
373 sizeof(ROOTHUB2_DEVICE_DESCRIPTOR
));
375 RootHubDevice
->DeviceDescriptor
.idVendor
= FdoDeviceExtension
->VendorId
;
376 RootHubDevice
->DeviceDescriptor
.idProduct
= FdoDeviceExtension
->DeviceId
;
378 RtlCopyMemory(&RootHubDevice
->ConfigurationDescriptor
,
379 ROOTHUB2_CONFIGURATION_DESCRIPTOR
,
380 sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR
));
382 PdoDeviceExtension
->UsbDevices
[0] = RootHubDevice
;
384 /* Create a thread to handle the URB's */
385 Status
= PsCreateSystemThread(&PdoDeviceExtension
->ThreadHandle
,
391 (PVOID
)PdoDeviceExtension
);
393 if (!NT_SUCCESS(Status
))
394 DPRINT1("Failed Thread Creation with Status: %x\n", Status
);
396 Status
= IoRegisterDeviceInterface(DeviceObject
, &GUID_DEVINTERFACE_USB_HUB
, NULL
, &InterfaceSymLinkName
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("Failed to register interface\n");
403 Status
= IoSetDeviceInterfaceState(&InterfaceSymLinkName
, TRUE
);
404 DPRINT1("Set interface state %x\n", Status
);
408 Status
= STATUS_SUCCESS
;
411 case IRP_MN_QUERY_DEVICE_RELATIONS
:
413 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
415 case TargetDeviceRelation
:
417 PDEVICE_RELATIONS DeviceRelations
= NULL
;
418 Status
= PdoQueryDeviceRelations(DeviceObject
, &DeviceRelations
);
419 Information
= (ULONG_PTR
)DeviceRelations
;
423 DPRINT1("BusRelations!!!!!\n");
424 case RemovalRelations
:
425 case EjectionRelations
:
427 /* Ignore the request */
428 Information
= Irp
->IoStatus
.Information
;
429 Status
= Irp
->IoStatus
.Status
;
435 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n",
436 Stack
->Parameters
.QueryDeviceRelations
.Type
);
437 Status
= STATUS_NOT_SUPPORTED
;
443 case IRP_MN_QUERY_CAPABILITIES
:
445 PDEVICE_CAPABILITIES DeviceCapabilities
;
448 DeviceCapabilities
= (PDEVICE_CAPABILITIES
)Stack
->Parameters
.DeviceCapabilities
.Capabilities
;
450 DeviceCapabilities
->LockSupported
= FALSE
;
451 DeviceCapabilities
->EjectSupported
= FALSE
;
452 DeviceCapabilities
->Removable
= FALSE
;
453 DeviceCapabilities
->DockDevice
= FALSE
;
454 DeviceCapabilities
->UniqueID
= FALSE
;
455 DeviceCapabilities
->SilentInstall
= FALSE
;
456 DeviceCapabilities
->RawDeviceOK
= FALSE
;
457 DeviceCapabilities
->SurpriseRemovalOK
= FALSE
;
458 DeviceCapabilities
->Address
= 0;
459 DeviceCapabilities
->UINumber
= 0;
460 DeviceCapabilities
->DeviceD2
= 1;
463 DeviceCapabilities
->HardwareDisabled
= FALSE
;
464 //DeviceCapabilities->NoDisplayInUI = FALSE;
465 DeviceCapabilities
->DeviceState
[0] = PowerDeviceD0
;
466 for (i
= 0; i
< PowerSystemMaximum
; i
++)
467 DeviceCapabilities
->DeviceState
[i
] = PowerDeviceD3
;
468 DeviceCapabilities
->DeviceWake
= 0;
469 DeviceCapabilities
->D1Latency
= 0;
470 DeviceCapabilities
->D2Latency
= 0;
471 DeviceCapabilities
->D3Latency
= 0;
473 Status
= STATUS_SUCCESS
;
476 /*case IRP_MN_QUERY_DEVICE_TEXT:
478 Status = STATUS_NOT_SUPPORTED;
482 case IRP_MN_QUERY_ID
:
484 Status
= PdoQueryId(DeviceObject
, Irp
, &Information
);
487 case IRP_MN_QUERY_INTERFACE
:
489 UNICODE_STRING GuidString
;
490 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub
;
491 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI
;
492 PPDO_DEVICE_EXTENSION PdoDeviceExtension
;
493 PFDO_DEVICE_EXTENSION FdoDeviceExtension
;
495 PdoDeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
496 FdoDeviceExtension
= (PFDO_DEVICE_EXTENSION
)PdoDeviceExtension
->ControllerFdo
->DeviceExtension
;
498 Status
= RtlStringFromGUID(Stack
->Parameters
.QueryInterface
.InterfaceType
, &GuidString
);
499 if (!NT_SUCCESS(Status
))
501 DPRINT1("Failed to create string from GUID!\n");
503 DPRINT1("Interface GUID requested %wZ\n", &GuidString
);
504 DPRINT1("QueryInterface.Size %x\n", Stack
->Parameters
.QueryInterface
.Size
);
505 DPRINT1("QueryInterface.Version %x\n", Stack
->Parameters
.QueryInterface
.Version
);
507 Status
= STATUS_SUCCESS
;
510 /* FIXME: Check the actual Guid */
511 if (Stack
->Parameters
.QueryInterface
.Size
== sizeof(USB_BUS_INTERFACE_USBDI_V2
) && (Stack
->Parameters
.QueryInterface
.Version
== 2))
513 InterfaceDI
= (PUSB_BUS_INTERFACE_USBDI_V2
) Stack
->Parameters
.QueryInterface
.Interface
;
514 InterfaceDI
->Size
= sizeof(USB_BUS_INTERFACE_USBDI_V2
);
515 InterfaceDI
->Version
= 2;
516 InterfaceDI
->BusContext
= PdoDeviceExtension
->DeviceObject
;
517 InterfaceDI
->InterfaceReference
= (PINTERFACE_REFERENCE
)InterfaceReference
;
518 InterfaceDI
->InterfaceDereference
= (PINTERFACE_DEREFERENCE
)InterfaceDereference
;
519 InterfaceDI
->GetUSBDIVersion
= GetUSBDIVersion
;
520 InterfaceDI
->QueryBusTime
= QueryBusTime
;
521 InterfaceDI
->SubmitIsoOutUrb
= SubmitIsoOutUrb
;
522 InterfaceDI
->QueryBusInformation
= QueryBusInformation
;
523 InterfaceDI
->IsDeviceHighSpeed
= IsDeviceHighSpeed
;
524 InterfaceDI
->EnumLogEntry
= EnumLogEntry
;
526 /* FIXME: Check the actual Guid */
527 else if (Stack
->Parameters
.QueryInterface
.Size
== sizeof(USB_BUS_INTERFACE_HUB_V5
) &&
528 (Stack
->Parameters
.QueryInterface
.Version
== 5))
530 InterfaceHub
= (PUSB_BUS_INTERFACE_HUB_V5
)Stack
->Parameters
.QueryInterface
.Interface
;
531 InterfaceHub
->Version
= 5;
532 InterfaceHub
->Size
= sizeof(USB_BUS_INTERFACE_HUB_V5
);
533 InterfaceHub
->BusContext
= PdoDeviceExtension
->DeviceObject
;
534 InterfaceHub
->InterfaceReference
= (PINTERFACE_REFERENCE
)InterfaceReference
;
535 InterfaceHub
->InterfaceDereference
= (PINTERFACE_DEREFERENCE
)InterfaceDereference
;
536 InterfaceHub
->CreateUsbDevice
= CreateUsbDevice
;
537 InterfaceHub
->InitializeUsbDevice
= InitializeUsbDevice
;
538 InterfaceHub
->GetUsbDescriptors
= GetUsbDescriptors
;
539 InterfaceHub
->RemoveUsbDevice
= RemoveUsbDevice
;
540 InterfaceHub
->RestoreUsbDevice
= RestoreUsbDevice
;
541 InterfaceHub
->GetPortHackFlags
= GetPortHackFlags
;
542 InterfaceHub
->QueryDeviceInformation
= QueryDeviceInformation
;
543 InterfaceHub
->GetControllerInformation
= GetControllerInformation
;
544 InterfaceHub
->ControllerSelectiveSuspend
= ControllerSelectiveSuspend
;
545 InterfaceHub
->GetExtendedHubInformation
= GetExtendedHubInformation
;
546 InterfaceHub
->GetRootHubSymbolicName
= GetRootHubSymbolicName
;
547 InterfaceHub
->GetDeviceBusContext
= GetDeviceBusContext
;
548 InterfaceHub
->Initialize20Hub
= Initialize20Hub
;
549 InterfaceHub
->RootHubInitNotification
= RootHubInitNotification
;
550 InterfaceHub
->FlushTransfers
= FlushTransfers
;
551 InterfaceHub
->SetDeviceHandleData
= SetDeviceHandleData
;
555 DPRINT1("Not Supported\n");
556 Status
= Irp
->IoStatus
.Status
;
557 Information
= Irp
->IoStatus
.Information
;
561 case IRP_MN_QUERY_BUS_INFORMATION
:
563 PPNP_BUS_INFORMATION BusInfo
;
565 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePool(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
567 Status
= STATUS_INSUFFICIENT_RESOURCES
;
572 &BusInfo->BusTypeGuid,
573 &GUID_DEVINTERFACE_XXX,
576 BusInfo
->LegacyBusType
= PNPBus
;
577 BusInfo
->BusNumber
= 0;
578 Information
= (ULONG_PTR
)BusInfo
;
579 Status
= STATUS_SUCCESS
;
585 /* We are the PDO. So ignore */
586 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction
);
591 Irp
->IoStatus
.Information
= Information
;
592 Irp
->IoStatus
.Status
= Status
;
593 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);