[USBAUDIO]
[reactos.git] / reactos / drivers / usb / usbehci / pdo.c
1 /*
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.
6 * PROGRAMMERS:
7 * Michael Martin (michael.martin@reactos.org)
8 */
9
10 #define INITGUID
11
12 #include "usbehci.h"
13 #include <hubbusif.h>
14 #include <usbbusif.h>
15 #include "usbiffn.h"
16 #include <wdmguid.h>
17 #include <stdio.h>
18 #include <debug.h>
19
20 /* Lifted from Linux with slight changes */
21 const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
22 {
23 0x12, /* bLength; */
24 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
25 0x00, 0x20, /* bcdUSB; v1.1 */
26 USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
27 0x01, /* bDeviceSubClass; */
28 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
29 0x08, /* bMaxPacketSize0; 8 Bytes */
30 /* Fill Vendor and Product in when init root hub */
31 0x00, 0x00, /* idVendor; */
32 0x00, 0x00, /* idProduct; */
33 0x00, 0x00, /* bcdDevice */
34 0x00, /* iManufacturer; */
35 0x00, /* iProduct; */
36 0x00, /* iSerialNumber; */
37 0x01 /* bNumConfigurations; */
38
39 };
40
41 const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
42 {
43 /* one configuration */
44 0x09, /* bLength; */
45 0x02, /* bDescriptorType; Configuration */
46 0x19, 0x00, /* wTotalLength; */
47 0x01, /* bNumInterfaces; (1) */
48 0x23, /* bConfigurationValue; */
49 0x00, /* iConfiguration; */
50 0x40, /* bmAttributes; */
51 0x00 /* MaxPower; */
52 };
53
54 const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
55 {
56 /* one interface */
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; */
66 };
67
68 const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
69 {
70 /* one endpoint (status change endpoint) */
71 0x07, /* bLength; */
72 0x05, /* bDescriptorType; Endpoint */
73 0x81, /* bEndpointAddress; IN Endpoint 1 */
74 0x03, /* bmAttributes; Interrupt */
75 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
76 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
77 };
78
79 NTSTATUS NTAPI
80 PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
81 {
82 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
83 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
84 PIO_STACK_LOCATION Stack = NULL;
85 NTSTATUS Status = STATUS_UNSUCCESSFUL;
86 ULONG_PTR Information = 0;
87 PEHCI_HOST_CONTROLLER hcd;
88
89 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
90 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
91
92 ASSERT(PdoDeviceExtension->Common.IsFdo == FALSE);
93
94 hcd = &FdoDeviceExtension->hcd;
95 Stack = IoGetCurrentIrpStackLocation(Irp);
96
97 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
98 {
99 case IOCTL_INTERNAL_USB_SUBMIT_URB:
100 {
101 PUSB_DEVICE UsbDevice = NULL;
102 URB *Urb;
103 ULONG i;
104
105 Urb = (PURB) Stack->Parameters.Others.Argument1;
106
107 UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
108
109 /* If there was no device passed then this URB is for the RootHub */
110 if (UsbDevice == NULL)
111 UsbDevice = PdoDeviceExtension->UsbDevices[0];
112
113 /* Check if it is a Status Change Endpoint (SCE). The Hub Driver sends this request and miniports mark the IRP pending
114 if there is no changes on any of the ports. When the DPC of miniport routine detects changes this IRP will be completed.
115 Based on XEN PV Usb Drivers */
116
117 if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
118 (UsbDevice == PdoDeviceExtension->UsbDevices[0]))
119 {
120 DPRINT("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
121 if (Urb->UrbBulkOrInterruptTransfer.PipeHandle != &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
122 {
123 DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
124 }
125
126 /* Queue the Irp first */
127 QueueURBRequest(PdoDeviceExtension, Irp);
128
129 /* Check for port changes */
130 if (EnumControllerPorts(hcd) == FALSE)
131 {
132 DPRINT("No port change\n");
133 Status = STATUS_PENDING;
134 IoMarkIrpPending(Irp);
135 break;
136 }
137
138 /* If we reached this point then port status has changed, so check
139 which port */
140 for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
141 {
142 if (hcd->Ports[i].PortChange == 0x01)
143 {
144 DPRINT1("On SCE request: Inform hub driver that port %d has changed\n", i+1);
145 ASSERT(FALSE);
146 ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
147 Information = 0;
148 Status = STATUS_SUCCESS;
149 /* Assume URB success */
150 Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
151 /* Set the DeviceHandle to the Internal Device */
152 Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
153
154 /* Request handled, Remove it from the queue */
155 RemoveUrbRequest(PdoDeviceExtension, Irp);
156 break;
157 }
158 }
159 if (Status == STATUS_SUCCESS) break;
160
161 IoMarkIrpPending(Irp);
162 Status = STATUS_PENDING;
163 break;
164 }
165
166 Status = HandleUrbRequest(PdoDeviceExtension, Irp);
167
168 break;
169 }
170 case IOCTL_INTERNAL_USB_CYCLE_PORT:
171 {
172 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
173 break;
174 }
175 case IOCTL_INTERNAL_USB_ENABLE_PORT:
176 {
177 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
178 Information = 0;
179 Status = STATUS_SUCCESS;
180 break;
181 }
182 case IOCTL_INTERNAL_USB_GET_BUS_INFO:
183 {
184 DPRINT1("IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
185 break;
186 }
187 case IOCTL_INTERNAL_USB_GET_BUSGUID_INFO:
188 {
189 DPRINT1("IOCTL_INTERNAL_USB_GET_BUSGUID_INFO\n");
190 break;
191 }
192 case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME:
193 {
194 DPRINT1("IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n");
195 break;
196 }
197 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
198 {
199 DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
200 if (Stack->Parameters.Others.Argument1)
201 {
202 /* Return the root hubs devicehandle */
203 DPRINT("Returning RootHub Handle %x\n", PdoDeviceExtension->UsbDevices[0]);
204 *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0];
205 Status = STATUS_SUCCESS;
206 }
207 else
208 Status = STATUS_INVALID_DEVICE_REQUEST;
209
210 break;
211
212 }
213 case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
214 {
215 DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
216 ASSERT(Stack->Parameters.Others.Argument1 != NULL);
217 if (Stack->Parameters.Others.Argument1)
218 {
219 /* FIXME: Determine the number of hubs between the usb device and root hub.
220 For now we have at least one. */
221 *(PULONG)Stack->Parameters.Others.Argument1 = 1;
222 }
223 Status = STATUS_SUCCESS;
224 break;
225 }
226 case IOCTL_INTERNAL_USB_GET_HUB_NAME:
227 {
228 DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_NAME\n");
229 break;
230 }
231 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
232 {
233 DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
234 break;
235 }
236 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
237 {
238 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
239 break;
240 }
241 case IOCTL_INTERNAL_USB_RESET_PORT:
242 {
243 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
244 break;
245 }
246 case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
247 {
248 DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
249 /* DDK documents that both the PDO and FDO are returned. However, while writing the UsbHub driver it was determine
250 that this was not the case. Windows usbehci driver gives the Pdo in both Arguments. Which makes sense as upper level
251 drivers should not be communicating with FDO. */
252 if (Stack->Parameters.Others.Argument1)
253 *(PVOID *)Stack->Parameters.Others.Argument1 = FdoDeviceExtension->Pdo;
254 if (Stack->Parameters.Others.Argument2)
255 *(PVOID *)Stack->Parameters.Others.Argument2 = FdoDeviceExtension->Pdo;
256 Information = 0;
257 Status = STATUS_SUCCESS;
258 break;
259 }
260 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
261 {
262 PUSB_IDLE_CALLBACK_INFO CallBackInfo;
263 DPRINT1("Ehci: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
264 /* FIXME: Set Callback for safe power down */
265 CallBackInfo = Stack->Parameters.DeviceIoControl.Type3InputBuffer;
266
267 PdoDeviceExtension->IdleCallback = CallBackInfo->IdleCallback;
268 PdoDeviceExtension->IdleContext = CallBackInfo->IdleContext;
269
270 Information = 0;
271 Status = STATUS_SUCCESS;
272 break;
273 }
274 default:
275 {
276 DPRINT1("Unhandled IoControlCode %x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
277 break;
278 }
279 }
280
281 Irp->IoStatus.Information = Information;
282
283 if (Status != STATUS_PENDING)
284 IoCompleteRequest(Irp, IO_NO_INCREMENT);
285
286 return Status;
287 }
288
289 NTSTATUS
290 PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
291 {
292 WCHAR Buffer[256];
293 ULONG Index = 0;
294 ULONG IdType;
295 UNICODE_STRING SourceString;
296 UNICODE_STRING String;
297 NTSTATUS Status;
298
299 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
300
301 switch (IdType)
302 {
303 case BusQueryDeviceID:
304 {
305 RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB20");
306 break;
307 }
308 case BusQueryHardwareIDs:
309 {
310 /* FIXME: Build from Device Vendor and Device ID */
311 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
312 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
313 Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
314
315 Buffer[Index] = UNICODE_NULL;
316 SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
317 SourceString.Buffer = Buffer;
318 break;
319
320 }
321 case BusQueryCompatibleIDs:
322 {
323 /* We have none */
324 return STATUS_SUCCESS;
325 }
326 case BusQueryInstanceID:
327 {
328 return STATUS_SUCCESS;
329 }
330 default:
331 {
332 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
333 return STATUS_NOT_SUPPORTED;
334 }
335 }
336
337 Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
338 &SourceString,
339 &String);
340
341 *Information = (ULONG_PTR)String.Buffer;
342 return Status;
343 }
344
345 NTSTATUS
346 PdoQueryDeviceRelations(PDEVICE_OBJECT DeviceObject, PDEVICE_RELATIONS* pDeviceRelations)
347 {
348 PDEVICE_RELATIONS DeviceRelations;
349
350 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
351 if (!DeviceRelations)
352 return STATUS_INSUFFICIENT_RESOURCES;
353
354 DeviceRelations->Count = 1;
355 DeviceRelations->Objects[0] = DeviceObject;
356 ObReferenceObject(DeviceObject);
357
358 *pDeviceRelations = DeviceRelations;
359 return STATUS_SUCCESS;
360 }
361
362 NTSTATUS NTAPI
363 PdoDispatchPnp(
364 IN PDEVICE_OBJECT DeviceObject,
365 IN PIRP Irp)
366 {
367 ULONG MinorFunction;
368 PIO_STACK_LOCATION Stack;
369 ULONG_PTR Information = Irp->IoStatus.Information;
370 NTSTATUS Status = Irp->IoStatus.Status;
371 PDEVICE_CAPABILITIES DeviceCapabilities;
372 ULONG i;
373
374 Stack = IoGetCurrentIrpStackLocation(Irp);
375 MinorFunction = Stack->MinorFunction;
376
377 switch (MinorFunction)
378 {
379 case IRP_MN_QUERY_REMOVE_DEVICE:
380 case IRP_MN_REMOVE_DEVICE:
381 case IRP_MN_CANCEL_REMOVE_DEVICE:
382 case IRP_MN_STOP_DEVICE:
383 case IRP_MN_QUERY_STOP_DEVICE:
384 case IRP_MN_CANCEL_STOP_DEVICE:
385 case IRP_MN_QUERY_DEVICE_TEXT:
386 case IRP_MN_SURPRISE_REMOVAL:
387 case IRP_MN_QUERY_RESOURCES:
388 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
389 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
390 {
391 Status = STATUS_SUCCESS;
392 break;
393 }
394
395 case IRP_MN_START_DEVICE:
396 {
397 PUSB_DEVICE RootHubDevice;
398 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
399 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
400 UNICODE_STRING InterfaceSymLinkName;
401
402 DPRINT1("Ehci: PDO StartDevice\n");
403 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
404 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
405
406 /* Create the root hub */
407 RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
408
409 RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
410 ROOTHUB2_DEVICE_DESCRIPTOR,
411 sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
412
413 RootHubDevice->DeviceDescriptor.idVendor = FdoDeviceExtension->VendorId;
414 RootHubDevice->DeviceDescriptor.idProduct = FdoDeviceExtension->DeviceId;
415
416 /* Here config, interfaces and descriptors are stored. This was duplicated from XEN PV Usb Drivers implementation.
417 Not sure that it is really needed as the information can be queueried from the device. */
418
419 RootHubDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
420 sizeof(PVOID) * RootHubDevice->DeviceDescriptor.bNumConfigurations,
421 USB_POOL_TAG);
422
423 RootHubDevice->Configs[0] = ExAllocatePoolWithTag(NonPagedPool,
424 sizeof(USB_CONFIGURATION) + sizeof(PVOID) * ROOTHUB2_CONFIGURATION_DESCRIPTOR[4],
425 USB_POOL_TAG);
426
427 RootHubDevice->Configs[0]->Interfaces[0] = ExAllocatePoolWithTag(NonPagedPool,
428 sizeof(USB_INTERFACE) + sizeof(PVOID) * ROOTHUB2_INTERFACE_DESCRIPTOR[4],
429 USB_POOL_TAG);
430
431 RootHubDevice->Configs[0]->Interfaces[0]->EndPoints[0] = ExAllocatePoolWithTag(NonPagedPool,
432 sizeof(USB_ENDPOINT),
433 USB_POOL_TAG);
434
435 RootHubDevice->ActiveConfig = RootHubDevice->Configs[0];
436 RootHubDevice->ActiveInterface = RootHubDevice->ActiveConfig->Interfaces[0];
437
438 RtlCopyMemory(&RootHubDevice->ActiveConfig->ConfigurationDescriptor,
439 ROOTHUB2_CONFIGURATION_DESCRIPTOR,
440 sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR));
441
442 RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->InterfaceDescriptor,
443 ROOTHUB2_INTERFACE_DESCRIPTOR,
444 sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR));
445
446 RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->EndPoints[0]->EndPointDescriptor,
447 ROOTHUB2_ENDPOINT_DESCRIPTOR,
448 sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR));
449 RootHubDevice->DeviceSpeed = UsbHighSpeed;
450 RootHubDevice->DeviceType = Usb20Device;
451
452 PdoDeviceExtension->UsbDevices[0] = RootHubDevice;
453
454 Status = IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_HUB, NULL, &InterfaceSymLinkName);
455 if (!NT_SUCCESS(Status))
456 {
457 DPRINT1("Failed to register interface\n");
458 return Status;
459 }
460 else
461 {
462 Status = IoSetDeviceInterfaceState(&InterfaceSymLinkName, TRUE);
463 if (!NT_SUCCESS(Status))
464 return Status;
465 }
466
467 Status = STATUS_SUCCESS;
468 break;
469 }
470 case IRP_MN_QUERY_DEVICE_RELATIONS:
471 {
472 DPRINT1("Ehci: PDO QueryDeviceRelations\n");
473 switch (Stack->Parameters.QueryDeviceRelations.Type)
474 {
475 case TargetDeviceRelation:
476 {
477 PDEVICE_RELATIONS DeviceRelations = NULL;
478 Status = PdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
479 Information = (ULONG_PTR)DeviceRelations;
480 break;
481 }
482 case BusRelations:
483 {
484 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
485 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
486
487 DPRINT("BusRelations!!!!!\n");
488
489 /* The hub driver has created the new device object and reported to pnp, as a result the pnp manager
490 has sent this IRP and type, so leave the next SCE request pending until a new device arrives.
491 Is there a better way to do this? */
492 ExAcquireFastMutex(&PdoDeviceExtension->ListLock);
493 PdoDeviceExtension->HaltQueue = TRUE;
494 ExReleaseFastMutex(&PdoDeviceExtension->ListLock);
495 }
496 case RemovalRelations:
497 case EjectionRelations:
498 {
499 /* Ignore the request */
500 Information = Irp->IoStatus.Information;
501 Status = Irp->IoStatus.Status;
502 break;
503
504 }
505 default:
506 {
507 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n",
508 Stack->Parameters.QueryDeviceRelations.Type);
509 Status = STATUS_NOT_SUPPORTED;
510 break;
511 }
512 }
513 break;
514 }
515 case IRP_MN_QUERY_CAPABILITIES:
516 {
517 DPRINT("Ehci: PDO Query Capabilities\n");
518
519 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
520
521 DeviceCapabilities->LockSupported = FALSE;
522 DeviceCapabilities->EjectSupported = FALSE;
523 DeviceCapabilities->Removable = FALSE;
524 DeviceCapabilities->DockDevice = FALSE;
525 DeviceCapabilities->UniqueID = FALSE;
526 DeviceCapabilities->SilentInstall = FALSE;
527 DeviceCapabilities->RawDeviceOK = FALSE;
528 DeviceCapabilities->SurpriseRemovalOK = FALSE;
529 DeviceCapabilities->Address = 0;
530 DeviceCapabilities->UINumber = 0;
531 DeviceCapabilities->DeviceD2 = 1;
532
533 /* FIXME: Verify these settings are correct */
534 DeviceCapabilities->HardwareDisabled = FALSE;
535 //DeviceCapabilities->NoDisplayInUI = FALSE;
536 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
537 for (i = 0; i < PowerSystemMaximum; i++)
538 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
539 DeviceCapabilities->DeviceWake = 0;
540 DeviceCapabilities->D1Latency = 0;
541 DeviceCapabilities->D2Latency = 0;
542 DeviceCapabilities->D3Latency = 0;
543 Information = 0;
544 Status = STATUS_SUCCESS;
545 break;
546 }
547 /*case IRP_MN_QUERY_DEVICE_TEXT:
548 {
549 Status = STATUS_NOT_SUPPORTED;
550 break;
551 }*/
552
553 case IRP_MN_QUERY_ID:
554 {
555 DPRINT("Ehci: PDO Query ID\n");
556 Status = PdoQueryId(DeviceObject, Irp, &Information);
557 break;
558 }
559 case IRP_MN_QUERY_INTERFACE:
560 {
561 UNICODE_STRING GuidString;
562 PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
563 PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
564 PPDO_DEVICE_EXTENSION PdoDeviceExtension;
565 PFDO_DEVICE_EXTENSION FdoDeviceExtension;
566
567 DPRINT("Ehci: PDO Query Interface\n");
568
569 PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
570 FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
571
572 Status = RtlStringFromGUID(Stack->Parameters.QueryInterface.InterfaceType, &GuidString);
573 if (!NT_SUCCESS(Status))
574 {
575 DPRINT1("Failed to create string from GUID!\n");
576 }
577
578 /* Assume success */
579 Status = STATUS_SUCCESS;
580 Information = 0;
581
582 if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID))
583 {
584 InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)Stack->Parameters.QueryInterface.Interface;
585 InterfaceHub->Version = Stack->Parameters.QueryInterface.Version;
586 if (Stack->Parameters.QueryInterface.Version >= 0)
587 {
588 InterfaceHub->Size = Stack->Parameters.QueryInterface.Size;
589 InterfaceHub->BusContext = PdoDeviceExtension->DeviceObject;
590 InterfaceHub->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
591 InterfaceHub->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
592 }
593 if (Stack->Parameters.QueryInterface.Version >= 1)
594 {
595 InterfaceHub->CreateUsbDevice = CreateUsbDevice;
596 InterfaceHub->InitializeUsbDevice = InitializeUsbDevice;
597 InterfaceHub->GetUsbDescriptors = GetUsbDescriptors;
598 InterfaceHub->RemoveUsbDevice = RemoveUsbDevice;
599 InterfaceHub->RestoreUsbDevice = RestoreUsbDevice;
600 InterfaceHub->GetPortHackFlags = GetPortHackFlags;
601 InterfaceHub->QueryDeviceInformation = QueryDeviceInformation;
602 }
603 if (Stack->Parameters.QueryInterface.Version >= 2)
604 {
605 InterfaceHub->GetControllerInformation = GetControllerInformation;
606 InterfaceHub->ControllerSelectiveSuspend = ControllerSelectiveSuspend;
607 InterfaceHub->GetExtendedHubInformation = GetExtendedHubInformation;
608 InterfaceHub->GetRootHubSymbolicName = GetRootHubSymbolicName;
609 InterfaceHub->GetDeviceBusContext = GetDeviceBusContext;
610 InterfaceHub->Initialize20Hub = Initialize20Hub;
611
612 }
613 if (Stack->Parameters.QueryInterface.Version >= 3)
614 {
615 InterfaceHub->RootHubInitNotification = RootHubInitNotification;
616 }
617 if (Stack->Parameters.QueryInterface.Version >= 4)
618 {
619 InterfaceHub->FlushTransfers = FlushTransfers;
620 }
621 if (Stack->Parameters.QueryInterface.Version >= 5)
622 {
623 InterfaceHub->SetDeviceHandleData = SetDeviceHandleData;
624 }
625 if (Stack->Parameters.QueryInterface.Version >= 6)
626 {
627 DPRINT1("USB_BUS_INTERFACE_HUB_GUID version not supported!\n");
628 }
629 break;
630 }
631
632 if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
633 {
634 InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) Stack->Parameters.QueryInterface.Interface;
635 InterfaceDI->Version = Stack->Parameters.QueryInterface.Version;
636 if (Stack->Parameters.QueryInterface.Version >= 0)
637 {
638 //InterfaceDI->Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
639 InterfaceDI->Size = Stack->Parameters.QueryInterface.Size;
640 InterfaceDI->BusContext = PdoDeviceExtension->DeviceObject;
641 InterfaceDI->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
642 InterfaceDI->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
643 InterfaceDI->GetUSBDIVersion = GetUSBDIVersion;
644 InterfaceDI->QueryBusTime = QueryBusTime;
645 InterfaceDI->SubmitIsoOutUrb = SubmitIsoOutUrb;
646 InterfaceDI->QueryBusInformation = QueryBusInformation;
647 }
648 if (Stack->Parameters.QueryInterface.Version >= 1)
649 {
650 InterfaceDI->IsDeviceHighSpeed = IsDeviceHighSpeed;
651 }
652 if (Stack->Parameters.QueryInterface.Version >= 2)
653 {
654 InterfaceDI->EnumLogEntry = EnumLogEntry;
655 }
656
657 if (Stack->Parameters.QueryInterface.Version >= 3)
658 {
659 DPRINT1("SB_BUS_INTERFACE_USBDI_GUID version not supported!\n");
660 }
661 break;
662 }
663
664 DPRINT1("GUID Not Supported\n");
665 Status = Irp->IoStatus.Status;
666 Information = Irp->IoStatus.Information;
667
668 break;
669 }
670 case IRP_MN_QUERY_BUS_INFORMATION:
671 {
672 PPNP_BUS_INFORMATION BusInfo;
673
674 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
675 if (!BusInfo)
676 Status = STATUS_INSUFFICIENT_RESOURCES;
677 else
678 {
679 /* FIXME */
680 /*RtlCopyMemory(
681 &BusInfo->BusTypeGuid,
682 &GUID_DEVINTERFACE_XXX,
683 sizeof(GUID));*/
684
685 BusInfo->LegacyBusType = PNPBus;
686 BusInfo->BusNumber = 0;
687 Information = (ULONG_PTR)BusInfo;
688 Status = STATUS_SUCCESS;
689 }
690 break;
691 }
692 default:
693 {
694 /* We are the PDO. So ignore */
695 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
696 break;
697 }
698 }
699
700 Irp->IoStatus.Information = Information;
701 Irp->IoStatus.Status = Status;
702 IoCompleteRequest(Irp, IO_NO_INCREMENT);
703 return Status;
704 }