xref: /reactos/drivers/usb/usbhub/pnp.c (revision ede7a20a)
1 /*
2  * PROJECT:     ReactOS USB Hub Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBHub plug and play functions
5  * COPYRIGHT:   Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 #include "usbhub.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 #define NDEBUG_USBHUB_PNP
14 #define NDEBUG_USBHUB_ENUM
15 #include "dbg_uhub.h"
16 
17 NTSTATUS
18 NTAPI
19 USBH_IrpCompletion(IN PDEVICE_OBJECT DeviceObject,
20                    IN PIRP Irp,
21                    IN PVOID Context)
22 {
23     PRKEVENT Event;
24 
25     DPRINT("USBH_IrpCompletion: Irp - %p\n", Irp);
26 
27     Event = Context;
28     KeSetEvent(Event, EVENT_INCREMENT, FALSE);
29     return STATUS_MORE_PROCESSING_REQUIRED;
30 }
31 
32 NTSTATUS
33 NTAPI
34 USBH_HubPnPIrpComplete(IN PDEVICE_OBJECT DeviceObject,
35                        IN PIRP Irp,
36                        IN PVOID Context)
37 {
38     PUSBHUB_FDO_EXTENSION HubExtension;
39 
40     DPRINT("USBH_HubPnPIrpComplete: Irp - %p\n", Irp);
41 
42      HubExtension = Context;
43 
44     if (!NT_SUCCESS(Irp->IoStatus.Status))
45     {
46         DPRINT1("USBH_HubPnPIrpComplete: Irp failed - %lX\n", Irp->IoStatus.Status);
47         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
48     }
49 
50     Irp->IoStatus.Status = STATUS_MORE_PROCESSING_REQUIRED;
51 
52     KeSetEvent(&HubExtension->LowerDeviceEvent, EVENT_INCREMENT, FALSE);
53 
54     return STATUS_MORE_PROCESSING_REQUIRED;
55 }
56 
57 NTSTATUS
58 NTAPI
59 USBH_QueryCapsComplete(IN PDEVICE_OBJECT DeviceObject,
60                        IN PIRP Irp,
61                        IN PVOID Context)
62 {
63     PIO_STACK_LOCATION IoStack;
64     PDEVICE_CAPABILITIES Capabilities;
65 
66     DPRINT("USBH_QueryCapsComplete: ... \n");
67 
68     ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
69 
70     if (Irp->PendingReturned)
71     {
72         IoMarkIrpPending(Irp);
73     }
74 
75     IoStack= IoGetCurrentIrpStackLocation(Irp);
76     Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
77 
78     Capabilities->SurpriseRemovalOK = 1;
79 
80     return STATUS_CONTINUE_COMPLETION;
81 }
82 
83 NTSTATUS
84 NTAPI
85 USBHUB_GetBusInterface(IN PDEVICE_OBJECT DeviceObject,
86                        OUT PUSB_BUS_INTERFACE_HUB_V5 BusInterface)
87 {
88     PIRP Irp;
89     NTSTATUS Status;
90     PIO_STACK_LOCATION IoStack;
91     KEVENT Event;
92 
93     DPRINT("USBHUB_GetBusInterface: ... \n");
94 
95     Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
96 
97     if (!Irp)
98     {
99         DPRINT1("USBHUB_GetBusInterface: IoAllocateIrp() failed\n");
100         return STATUS_INSUFFICIENT_RESOURCES;
101     }
102 
103     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
104 
105     KeInitializeEvent(&Event, NotificationEvent, FALSE);
106 
107     IoSetCompletionRoutine(Irp,
108                            USBH_IrpCompletion,
109                            &Event,
110                            TRUE,
111                            TRUE,
112                            TRUE);
113 
114     IoStack = IoGetNextIrpStackLocation(Irp);
115 
116     IoStack->MajorFunction = IRP_MJ_PNP;
117     IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
118 
119     IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_HUB_GUID;
120     IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_HUB_V5);
121     IoStack->Parameters.QueryInterface.Version = USB_BUSIF_HUB_VERSION_5;
122     IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
123     IoStack->Parameters.QueryInterface.InterfaceSpecificData = DeviceObject;
124 
125     Status = IoCallDriver(DeviceObject, Irp);
126 
127     if (Status == STATUS_PENDING)
128     {
129         KeWaitForSingleObject(&Event,
130                               Suspended,
131                               KernelMode,
132                               FALSE,
133                               NULL);
134 
135         Status = Irp->IoStatus.Status;
136     }
137 
138     IoFreeIrp(Irp);
139 
140     return Status;
141 }
142 
143 NTSTATUS
144 NTAPI
145 USBHUB_GetBusInterfaceUSBDI(IN PDEVICE_OBJECT DeviceObject,
146                             OUT PUSB_BUS_INTERFACE_USBDI_V2 BusInterfaceUSBDI)
147 {
148     PIRP Irp;
149     NTSTATUS Status;
150     PIO_STACK_LOCATION IoStack;
151     KEVENT Event;
152 
153     DPRINT("USBHUB_GetBusInterfaceUSBDI: ... \n");
154 
155     Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
156 
157     if (!Irp)
158     {
159         DPRINT1("USBHUB_GetBusInterfaceUSBDI: IoAllocateIrp() failed\n");
160         return STATUS_INSUFFICIENT_RESOURCES;
161     }
162 
163     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
164 
165     KeInitializeEvent(&Event, NotificationEvent, FALSE);
166 
167     IoSetCompletionRoutine(Irp,
168                            USBH_IrpCompletion,
169                            &Event,
170                            TRUE,
171                            TRUE,
172                            TRUE);
173 
174     IoStack = IoGetNextIrpStackLocation(Irp);
175 
176     IoStack->MajorFunction = IRP_MJ_PNP;
177     IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
178 
179     IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID;
180     IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
181     IoStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_2;
182     IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterfaceUSBDI;
183     IoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
184 
185     Status = IoCallDriver(DeviceObject, Irp);
186 
187     if (Status == STATUS_PENDING)
188     {
189         KeWaitForSingleObject(&Event,
190                               Suspended,
191                               KernelMode,
192                               FALSE,
193                               NULL);
194 
195         Status = Irp->IoStatus.Status;
196     }
197 
198     IoFreeIrp(Irp);
199 
200     return Status;
201 }
202 
203 VOID
204 NTAPI
205 USBH_QueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
206                        IN PDEVICE_CAPABILITIES DeviceCapabilities)
207 {
208     PIRP Irp;
209     PIO_STACK_LOCATION IoStack;
210     KEVENT Event;
211 
212     DPRINT("USBH_QueryCapabilities: ... \n");
213 
214     RtlZeroMemory(DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
215 
216     Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
217 
218     if (!Irp)
219     {
220         DPRINT1("USBH_QueryCapabilities: IoAllocateIrp() failed\n");
221         return;
222     }
223 
224     Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
225 
226     KeInitializeEvent(&Event, NotificationEvent, FALSE);
227 
228     IoSetCompletionRoutine(Irp,
229                            USBH_IrpCompletion,
230                            &Event,
231                            TRUE,
232                            TRUE,
233                            TRUE);
234 
235     IoStack = IoGetNextIrpStackLocation(Irp);
236 
237     IoStack->MajorFunction = IRP_MJ_PNP;
238     IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
239 
240     IoStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
241     IoStack->Parameters.DeviceCapabilities.Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
242     IoStack->Parameters.DeviceCapabilities.Capabilities->Version = 1;
243     IoStack->Parameters.DeviceCapabilities.Capabilities->Address = MAXULONG;
244     IoStack->Parameters.DeviceCapabilities.Capabilities->UINumber = MAXULONG;
245 
246     if (IoCallDriver(DeviceObject, Irp) == STATUS_PENDING)
247     {
248         KeWaitForSingleObject(&Event,
249                               Suspended,
250                               KernelMode,
251                               FALSE,
252                               NULL);
253     }
254 
255     IoFreeIrp(Irp);
256 }
257 
258 NTSTATUS
259 NTAPI
260 USBH_OpenConfiguration(IN PUSBHUB_FDO_EXTENSION HubExtension)
261 {
262     PUSB_INTERFACE_DESCRIPTOR Pid;
263     PURB Urb;
264     NTSTATUS Status;
265     USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
266 
267     DPRINT("USBH_OpenConfiguration ... \n");
268 
269     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB &&
270         HubExtension->LowerPDO != HubExtension->RootHubPdo)
271     {
272         Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor,
273                                                   HubExtension->HubConfigDescriptor,
274                                                   -1,
275                                                   -1,
276                                                   USB_DEVICE_CLASS_HUB,
277                                                   -1,
278                                                   2);
279 
280         if (Pid)
281         {
282             HubExtension->HubFlags |= USBHUB_FDO_FLAG_MULTIPLE_TTS;
283         }
284         else
285         {
286             Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor,
287                                                       HubExtension->HubConfigDescriptor,
288                                                       -1,
289                                                       -1,
290                                                       USB_DEVICE_CLASS_HUB,
291                                                       -1,
292                                                       1);
293 
294             if (Pid)
295             {
296                 goto Next;
297             }
298 
299             Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor,
300                                                       HubExtension->HubConfigDescriptor,
301                                                       -1,
302                                                       -1,
303                                                       USB_DEVICE_CLASS_HUB,
304                                                       -1,
305                                                       0);
306         }
307     }
308     else
309     {
310         Pid = USBD_ParseConfigurationDescriptorEx(HubExtension->HubConfigDescriptor,
311                                                   HubExtension->HubConfigDescriptor,
312                                                   -1,
313                                                   -1,
314                                                   USB_DEVICE_CLASS_HUB,
315                                                   -1,
316                                                   -1);
317     }
318 
319     if (!Pid)
320     {
321         return STATUS_UNSUCCESSFUL;
322     }
323 
324   Next:
325 
326     if (Pid->bInterfaceClass != USB_DEVICE_CLASS_HUB)
327     {
328         return STATUS_UNSUCCESSFUL;
329     }
330 
331     InterfaceList[0].InterfaceDescriptor = Pid;
332 
333     Urb = USBD_CreateConfigurationRequestEx(HubExtension->HubConfigDescriptor,
334                                             InterfaceList);
335 
336     if (!Urb)
337     {
338         return STATUS_INSUFFICIENT_RESOURCES;
339     }
340 
341     Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, Urb);
342 
343     if (NT_SUCCESS(Status))
344     {
345         RtlCopyMemory(&HubExtension->PipeInfo,
346                       InterfaceList[0].Interface->Pipes,
347                       sizeof(USBD_PIPE_INFORMATION));
348 
349         HubExtension->ConfigHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
350     }
351 
352     ExFreePool(Urb);
353 
354     return Status;
355 }
356 
357 NTSTATUS
358 NTAPI
359 USBD_Initialize20Hub(IN PUSBHUB_FDO_EXTENSION HubExtension)
360 {
361     PUSB_BUSIFFN_INITIALIZE_20HUB Initialize20Hub;
362     ULONG TtCount;
363     PUSB_DEVICE_HANDLE DeviceHandle;
364 
365     DPRINT("USBD_InitUsb2Hub ... \n");
366 
367     Initialize20Hub = HubExtension->BusInterface.Initialize20Hub;
368 
369     if (!Initialize20Hub)
370     {
371         return STATUS_NOT_IMPLEMENTED;
372     }
373 
374     TtCount = 1;
375 
376     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_MULTIPLE_TTS)
377     {
378         TtCount = HubExtension->HubDescriptor->bNumberOfPorts;
379     }
380 
381     DeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
382 
383     return Initialize20Hub(HubExtension->BusInterface.BusContext,
384                            DeviceHandle,
385                            TtCount);
386 }
387 
388 NTSTATUS
389 NTAPI
390 USBH_AbortInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension)
391 {
392     struct _URB_PIPE_REQUEST * Urb;
393     NTSTATUS Status;
394 
395     DPRINT("USBH_AbortInterruptPipe: HubExtension - %p\n", HubExtension);
396 
397     Urb = ExAllocatePoolWithTag(NonPagedPool,
398                                 sizeof(struct _URB_PIPE_REQUEST),
399                                 USB_HUB_TAG);
400 
401     if (!Urb)
402     {
403         return STATUS_INSUFFICIENT_RESOURCES;
404     }
405 
406     RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST));
407 
408     Urb->Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
409     Urb->Hdr.Function = URB_FUNCTION_ABORT_PIPE;
410     Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
411 
412     Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice,
413                                    (PURB)Urb);
414 
415     if (NT_SUCCESS(Status))
416     {
417         KeWaitForSingleObject(&HubExtension->StatusChangeEvent,
418                               Suspended,
419                               KernelMode,
420                               FALSE,
421                               NULL);
422     }
423 
424     ExFreePoolWithTag(Urb, USB_HUB_TAG);
425 
426     return Status;
427 }
428 
429 VOID
430 NTAPI
431 USBH_FdoCleanup(IN PUSBHUB_FDO_EXTENSION HubExtension)
432 {
433     PIRP IdleIrp = NULL;
434     PIRP WakeIrp = NULL;
435     PUSBHUB_PORT_DATA PortData;
436     PUSBHUB_PORT_PDO_EXTENSION PortExtension;
437     PIRP PortIdleIrp = NULL;
438     PIRP PortWakeIrp = NULL;
439     PVOID DeviceHandle;
440     NTSTATUS Status;
441     USHORT Port;
442     UCHAR NumberPorts;
443     KIRQL Irql;
444 
445     DPRINT("USBH_FdoCleanup: HubExtension - %p\n", HubExtension);
446 
447     USBD_UnRegisterRootHubCallBack(HubExtension);
448 
449     HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_STOPPING;
450 
451     if (HubExtension->ResetRequestCount)
452     {
453         IoCancelIrp(HubExtension->ResetPortIrp);
454 
455         KeWaitForSingleObject(&HubExtension->IdleEvent,
456                               Suspended,
457                               KernelMode,
458                               FALSE,
459                               NULL);
460     }
461 
462     IoFreeIrp(HubExtension->ResetPortIrp);
463 
464     HubExtension->ResetPortIrp = NULL;
465 
466     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
467     {
468         KeWaitForSingleObject(&HubExtension->IdleEvent,
469                               Suspended,
470                               KernelMode,
471                               FALSE,
472                               NULL);
473     }
474 
475     IoAcquireCancelSpinLock(&Irql);
476 
477     if (HubExtension->PendingWakeIrp)
478     {
479         WakeIrp = HubExtension->PendingWakeIrp;
480         HubExtension->PendingWakeIrp = NULL;
481     }
482 
483     if (HubExtension->PendingIdleIrp)
484     {
485         IdleIrp = HubExtension->PendingIdleIrp;
486         HubExtension->PendingIdleIrp = NULL;
487     }
488 
489     IoReleaseCancelSpinLock(Irql);
490 
491     if (WakeIrp)
492     {
493         USBH_HubCancelWakeIrp(HubExtension, WakeIrp);
494     }
495 
496     USBH_HubCompletePortWakeIrps(HubExtension, STATUS_DELETE_PENDING);
497 
498     if (IdleIrp)
499     {
500         USBH_HubCancelIdleIrp(HubExtension, IdleIrp);
501     }
502 
503     if (InterlockedDecrement(&HubExtension->PendingRequestCount) > 0)
504     {
505         KeWaitForSingleObject(&HubExtension->PendingRequestEvent,
506                               Suspended,
507                               KernelMode,
508                               FALSE,
509                               NULL);
510     }
511 
512     if (HubExtension->SCEIrp)
513     {
514         Status = USBH_AbortInterruptPipe(HubExtension);
515 
516         if (!NT_SUCCESS(Status) && IoCancelIrp(HubExtension->SCEIrp))
517         {
518             KeWaitForSingleObject(&HubExtension->StatusChangeEvent,
519                                   Suspended,
520                                   KernelMode,
521                                   FALSE,
522                                   NULL);
523         }
524 
525         IoFreeIrp(HubExtension->SCEIrp);
526 
527         HubExtension->SCEIrp = NULL;
528     }
529 
530     if (!HubExtension->PortData ||
531         !HubExtension->HubDescriptor)
532     {
533         goto Exit;
534     }
535 
536     PortData = HubExtension->PortData;
537     NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts;
538 
539     for (Port = 0; Port < NumberPorts; Port++)
540     {
541         if (PortData[Port].DeviceObject)
542         {
543             PortExtension = PortData[Port].DeviceObject->DeviceExtension;
544 
545             IoAcquireCancelSpinLock(&Irql);
546 
547             PortIdleIrp = PortExtension->IdleNotificationIrp;
548 
549             if (PortIdleIrp)
550             {
551                 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION;
552                 PortExtension->IdleNotificationIrp = NULL;
553 
554                 if (PortIdleIrp->Cancel)
555                 {
556                     PortIdleIrp = NULL;
557                 }
558 
559                 if (PortIdleIrp)
560                 {
561                     IoSetCancelRoutine(PortIdleIrp, NULL);
562                 }
563             }
564 
565             PortWakeIrp = PortExtension->PdoWaitWakeIrp;
566 
567             if (PortWakeIrp)
568             {
569                 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_WAIT_WAKE;
570                 PortExtension->PdoWaitWakeIrp = NULL;
571 
572                 if (PortWakeIrp->Cancel || !IoSetCancelRoutine(PortWakeIrp, NULL))
573                 {
574                     PortWakeIrp = NULL;
575 
576                     if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
577                     {
578                         KeSetEvent(&HubExtension->PendingRequestEvent,
579                                    EVENT_INCREMENT,
580                                    FALSE);
581                     }
582                 }
583             }
584 
585             IoReleaseCancelSpinLock(Irql);
586 
587             if (PortIdleIrp)
588             {
589                 PortIdleIrp->IoStatus.Status = STATUS_CANCELLED;
590                 IoCompleteRequest(PortIdleIrp, IO_NO_INCREMENT);
591             }
592 
593             if (PortWakeIrp)
594             {
595                 USBH_CompletePowerIrp(HubExtension,
596                                       PortWakeIrp,
597                                       STATUS_CANCELLED);
598             }
599 
600             if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3))
601             {
602                 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
603                                                           NULL);
604 
605                 if (DeviceHandle)
606                 {
607                     USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
608                 }
609 
610                 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_POWER_D3;
611             }
612         }
613 
614         USBH_SyncDisablePort(HubExtension, Port + 1);
615     }
616 
617 Exit:
618 
619     if (HubExtension->SCEBitmap)
620     {
621         ExFreePoolWithTag(HubExtension->SCEBitmap, USB_HUB_TAG);
622     }
623 
624     if (HubExtension->HubDescriptor)
625     {
626         ExFreePoolWithTag(HubExtension->HubDescriptor, USB_HUB_TAG);
627     }
628 
629     if (HubExtension->HubConfigDescriptor)
630     {
631         ExFreePoolWithTag(HubExtension->HubConfigDescriptor, USB_HUB_TAG);
632     }
633 
634     HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DEVICE_STARTED;
635 
636     HubExtension->HubDescriptor = NULL;
637     HubExtension->HubConfigDescriptor = NULL;
638 
639     HubExtension->SCEIrp = NULL;
640     HubExtension->SCEBitmap = NULL;
641 }
642 
643 NTSTATUS
644 NTAPI
645 USBH_StartHubFdoDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
646                        IN PIRP Irp)
647 {
648     NTSTATUS Status;
649     ULONG DisableRemoteWakeup = 0;
650     ULONG HubCount = 0;
651     PUSB_DEVICE_HANDLE DeviceHandle;
652     USB_DEVICE_TYPE DeviceType;
653     DEVICE_CAPABILITIES  DeviceCapabilities;
654     BOOLEAN IsBusPowered;
655     static WCHAR DisableWakeValueName[] = L"DisableRemoteWakeup";
656 
657     DPRINT("USBH_StartHubFdoDevice: ... \n");
658 
659     KeInitializeEvent(&HubExtension->IdleEvent, NotificationEvent, FALSE);
660     KeInitializeEvent(&HubExtension->ResetEvent, NotificationEvent, TRUE);
661     KeInitializeEvent(&HubExtension->PendingRequestEvent, NotificationEvent, FALSE);
662     KeInitializeEvent(&HubExtension->LowerDeviceEvent, NotificationEvent, FALSE);
663     KeInitializeEvent(&HubExtension->StatusChangeEvent, NotificationEvent, TRUE);
664     KeInitializeEvent(&HubExtension->RootHubNotificationEvent,
665                       NotificationEvent,
666                       TRUE);
667 
668     KeInitializeSpinLock(&HubExtension->RelationsWorkerSpinLock);
669     KeInitializeSpinLock(&HubExtension->CheckIdleSpinLock);
670 
671     KeInitializeSemaphore(&HubExtension->ResetDeviceSemaphore, 1, 1);
672     KeInitializeSemaphore(&HubExtension->HubPortSemaphore, 1, 1);
673     KeInitializeSemaphore(&HubExtension->HubSemaphore, 1, 1);
674 
675     HubExtension->HubFlags = 0;
676     HubExtension->HubConfigDescriptor = NULL;
677     HubExtension->HubDescriptor = NULL;
678     HubExtension->SCEIrp = NULL;
679     HubExtension->SCEBitmap = NULL;
680     HubExtension->SystemPowerState.SystemState = PowerSystemWorking;
681     HubExtension->PendingRequestCount = 1;
682     HubExtension->ResetRequestCount = 0;
683     HubExtension->PendingIdleIrp = NULL;
684     HubExtension->PendingWakeIrp = NULL;
685 
686     InitializeListHead(&HubExtension->PdoList);
687 
688     HubExtension->HubFlags |= USBHUB_FDO_FLAG_WITEM_INIT;
689     InitializeListHead(&HubExtension->WorkItemList);
690     KeInitializeSpinLock(&HubExtension->WorkItemSpinLock);
691 
692     IoCopyCurrentIrpStackLocationToNext(Irp);
693 
694     IoSetCompletionRoutine(Irp,
695                            USBH_HubPnPIrpComplete,
696                            HubExtension,
697                            TRUE,
698                            TRUE,
699                            TRUE);
700 
701     if (IoCallDriver(HubExtension->LowerDevice, Irp) == STATUS_PENDING)
702     {
703         KeWaitForSingleObject(&HubExtension->LowerDeviceEvent,
704                               Suspended,
705                               KernelMode,
706                               FALSE,
707                               NULL);
708     }
709 
710     HubExtension->RootHubPdo = NULL;
711 
712     Status = USBH_SyncGetRootHubPdo(HubExtension->LowerDevice,
713                                     &HubExtension->RootHubPdo,
714                                     &HubExtension->RootHubPdo2);
715 
716     if (!NT_SUCCESS(Status))
717     {
718         DPRINT1("USBH_SyncGetRootHubPdo() failed - %lX\n", Status);
719         goto ErrorExit;
720     }
721 
722     USBH_WriteFailReasonID(HubExtension->LowerPDO, USBHUB_FAIL_NO_FAIL);
723 
724     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED)
725     {
726         DPRINT1("USBH_StartHubFdoDevice: USBHUB_FDO_FLAG_DEVICE_FAILED - TRUE\n");
727         Status = STATUS_UNSUCCESSFUL;
728         goto ErrorExit;
729     }
730 
731     HubExtension->HubFlags |= USBHUB_FDO_FLAG_REMOTE_WAKEUP;
732 
733     Status = USBD_GetPdoRegistryParameter(HubExtension->LowerPDO,
734                                           &DisableRemoteWakeup,
735                                           sizeof(DisableRemoteWakeup),
736                                           DisableWakeValueName,
737                                           sizeof(DisableWakeValueName));
738 
739     if (NT_SUCCESS(Status) && DisableRemoteWakeup)
740     {
741         DPRINT("USBH_StartHubFdoDevice: DisableRemoteWakeup - TRUE\n");
742         HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_REMOTE_WAKEUP;
743     }
744 
745     HubExtension->CurrentPowerState.DeviceState = PowerDeviceD0;
746 
747     USBH_SyncGetHubCount(HubExtension->LowerDevice,
748                          &HubCount);
749 
750     Status = USBHUB_GetBusInterface(HubExtension->RootHubPdo,
751                                     &HubExtension->BusInterface);
752 
753     if (!NT_SUCCESS(Status))
754     {
755         DPRINT1("USBH_StartHubFdoDevice: USBHUB_GetBusInterface() failed - %lX\n",
756                 Status);
757         goto ErrorExit;
758     }
759 
760     Status = USBHUB_GetBusInterfaceUSBDI(HubExtension->LowerDevice,
761                                          &HubExtension->BusInterfaceUSBDI);
762 
763     if (!NT_SUCCESS(Status))
764     {
765         DPRINT1("USBH_StartHubFdoDevice: USBHUB_GetBusInterfaceUSBDI() failed - %lX\n",
766                 Status);
767         goto ErrorExit;
768     }
769 
770     DeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
771 
772     if (DeviceHandle)
773     {
774         Status = USBH_GetDeviceType(HubExtension, DeviceHandle, &DeviceType);
775 
776         if (!NT_SUCCESS(Status))
777         {
778             DPRINT1("USBH_StartHubFdoDevice: USBH_GetDeviceType() failed - %lX\n",
779                     Status);
780 
781             goto ErrorExit;
782         }
783 
784         if (DeviceType == Usb20Device)
785         {
786             HubExtension->HubFlags |= USBHUB_FDO_FLAG_USB20_HUB;
787         }
788     }
789 
790     if (HubCount > USBHUB_MAX_CASCADE_LEVELS)
791     {
792         PUSBHUB_PORT_PDO_EXTENSION ParentPdoExtension;
793         PUSBHUB_FDO_EXTENSION ParentHubExtension;
794         USHORT ParentPort;
795         PUSBHUB_PORT_DATA PortData;
796 
797         DPRINT1("USBH_StartHubFdoDevice: HubCount > 6 - %x\n", HubCount);
798 
799         USBH_WriteFailReasonID(HubExtension->LowerPDO,
800                                USBHUB_FAIL_NESTED_TOO_DEEPLY);
801 
802         ParentPdoExtension = HubExtension->LowerPDO->DeviceExtension;
803         ParentHubExtension = ParentPdoExtension->HubExtension;
804 
805         ParentPort = ParentPdoExtension->PortNumber - 1;
806         PortData = &ParentHubExtension->PortData[ParentPort];
807         PortData->ConnectionStatus = DeviceHubNestedTooDeeply;
808 
809         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
810     }
811 
812     USBH_QueryCapabilities(HubExtension->LowerDevice, &DeviceCapabilities);
813 
814     HubExtension->SystemWake = DeviceCapabilities.SystemWake;
815     HubExtension->DeviceWake = DeviceCapabilities.DeviceWake;
816 
817     RtlCopyMemory(HubExtension->DeviceState,
818                   &DeviceCapabilities.DeviceState,
819                   POWER_SYSTEM_MAXIMUM * sizeof(DEVICE_POWER_STATE));
820 
821     Status = USBH_GetDeviceDescriptor(HubExtension->Common.SelfDevice,
822                                       &HubExtension->HubDeviceDescriptor);
823 
824     if (!NT_SUCCESS(Status))
825     {
826         DPRINT1("USBH_StartHubFdoDevice: USBH_GetDeviceDescriptor() failed - %lX\n",
827                 Status);
828         goto ErrorExit;
829     }
830 
831     Status = USBH_GetConfigurationDescriptor(HubExtension->Common.SelfDevice,
832                                              &HubExtension->HubConfigDescriptor);
833 
834     if (!NT_SUCCESS(Status))
835     {
836         DPRINT1("USBH_StartHubFdoDevice: USBH_GetConfigurationDescriptor() failed - %lX\n",
837                 Status);
838         goto ErrorExit;
839     }
840 
841     Status = USBH_SyncGetHubDescriptor(HubExtension);
842 
843     if (!NT_SUCCESS(Status))
844     {
845         DPRINT1("USBH_StartHubFdoDevice: USBH_SyncGetHubDescriptor() failed - %lX\n",
846                 Status);
847         goto ErrorExit;
848     }
849 
850     IsBusPowered = USBH_HubIsBusPowered(HubExtension->Common.SelfDevice,
851                                         HubExtension->HubConfigDescriptor);
852 
853     if (IsBusPowered)
854     {
855         /* bus-powered hub is allowed a maximum of 100 mA only for each port */
856         HubExtension->MaxPowerPerPort = 100;
857 
858         /* can have 4 ports (4 * 100 mA) and 100 mA remains for itself;
859            expressed in 2 mA units (i.e., 250 = 500 mA). */
860         HubExtension->HubConfigDescriptor->MaxPower = 250;
861     }
862     else
863     {
864         /* self-powered hub is allowed a maximum of 500 mA for each port */
865         HubExtension->MaxPowerPerPort = 500;
866     }
867 
868     Status = USBH_OpenConfiguration(HubExtension);
869 
870     if (!NT_SUCCESS(Status))
871     {
872         DPRINT1("USBH_StartHubFdoDevice: USBH_OpenConfiguration() failed - %lX\n",
873                 Status);
874         goto ErrorExit;
875     }
876 
877     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)
878     {
879         Status = USBD_Initialize20Hub(HubExtension);
880     }
881 
882     if (!NT_SUCCESS(Status))
883     {
884         goto ErrorExit;
885     }
886 
887     HubExtension->SCEIrp = IoAllocateIrp(HubExtension->Common.SelfDevice->StackSize,
888                                          FALSE);
889 
890     HubExtension->ResetPortIrp = IoAllocateIrp(HubExtension->Common.SelfDevice->StackSize,
891                                                FALSE);
892 
893     if (!HubExtension->SCEIrp || !HubExtension->ResetPortIrp)
894     {
895         Status = STATUS_INSUFFICIENT_RESOURCES;
896         goto ErrorExit;
897     }
898 
899     HubExtension->SCEBitmapLength = HubExtension->PipeInfo.MaximumPacketSize;
900 
901     HubExtension->SCEBitmap = ExAllocatePoolWithTag(NonPagedPool,
902                                                     HubExtension->SCEBitmapLength,
903                                                     USB_HUB_TAG);
904 
905     if (!HubExtension->SCEBitmap)
906     {
907         Status = STATUS_INSUFFICIENT_RESOURCES;
908         goto ErrorExit;
909     }
910 
911     RtlZeroMemory(HubExtension->SCEBitmap, HubExtension->SCEBitmapLength);
912 
913     Status = USBH_SyncPowerOnPorts(HubExtension);
914 
915     if (!NT_SUCCESS(Status))
916     {
917         goto ErrorExit;
918     }
919     else
920     {
921         USHORT Port;
922 
923         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_STARTED;
924 
925         for (Port = 1;
926              Port <= HubExtension->HubDescriptor->bNumberOfPorts;
927              Port++)
928         {
929             USBH_SyncClearPortStatus(HubExtension,
930                                      Port,
931                                      USBHUB_FEATURE_C_PORT_CONNECTION);
932         }
933     }
934 
935     if (HubExtension->LowerPDO == HubExtension->RootHubPdo)
936     {
937         USBD_RegisterRootHubCallBack(HubExtension);
938     }
939     else
940     {
941         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION;
942         USBH_SubmitStatusChangeTransfer(HubExtension);
943     }
944 
945     goto Exit;
946 
947   ErrorExit:
948 
949     if (HubExtension->HubDescriptor)
950     {
951         ExFreePoolWithTag(HubExtension->HubDescriptor, USB_HUB_TAG);
952         HubExtension->HubDescriptor = NULL;
953     }
954 
955     if (HubExtension->SCEIrp)
956     {
957         IoFreeIrp(HubExtension->SCEIrp);
958         HubExtension->SCEIrp = NULL;
959     }
960 
961     if (HubExtension->ResetPortIrp)
962     {
963         IoFreeIrp(HubExtension->ResetPortIrp);
964         HubExtension->ResetPortIrp = NULL;
965     }
966 
967     if (HubExtension->SCEBitmap)
968     {
969         ExFreePoolWithTag(HubExtension->SCEBitmap, USB_HUB_TAG);
970         HubExtension->SCEBitmap = NULL;
971     }
972 
973     if (HubExtension->HubConfigDescriptor)
974     {
975         ExFreePoolWithTag(HubExtension->HubConfigDescriptor, USB_HUB_TAG);
976         HubExtension->HubConfigDescriptor = NULL;
977     }
978 
979   Exit:
980 
981     USBH_CompleteIrp(Irp, Status);
982 
983     return Status;
984 }
985 
986 NTSTATUS
987 NTAPI
988 USBH_FdoStartDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
989                     IN PIRP Irp)
990 {
991     NTSTATUS Status;
992 
993     DPRINT("USBH_FdoStartDevice: HubExtension - %p\n", HubExtension);
994 
995     HubExtension->RootHubPdo = NULL;
996 
997     Status = USBH_SyncGetRootHubPdo(HubExtension->LowerDevice,
998                                     &HubExtension->RootHubPdo,
999                                     &HubExtension->RootHubPdo2);
1000 
1001     if (NT_SUCCESS(Status))
1002     {
1003         if (HubExtension->RootHubPdo)
1004         {
1005             Status = USBH_StartHubFdoDevice(HubExtension, Irp);
1006         }
1007         else
1008         {
1009             DPRINT1("USBH_FdoStartDevice: FIXME. start ParentDevice\n");
1010             DbgBreakPoint();
1011         }
1012     }
1013     else
1014     {
1015         DPRINT1("USBH_FdoStartDevice: FIXME. USBH_SyncGetRootHubPdo return - %lX\n",
1016                 Status);
1017 
1018         DbgBreakPoint();
1019         USBH_CompleteIrp(Irp, Status);
1020     }
1021 
1022     return Status;
1023 }
1024 
1025 NTSTATUS
1026 NTAPI
1027 USBH_FdoQueryBusRelations(IN PUSBHUB_FDO_EXTENSION HubExtension,
1028                           IN PIRP Irp)
1029 {
1030     PDEVICE_RELATIONS DeviceRelations = NULL;
1031     NTSTATUS Status = STATUS_SUCCESS;
1032     LIST_ENTRY GhostPdoList;
1033     KIRQL OldIrql;
1034     PLIST_ENTRY PdoList;
1035     UCHAR NumberPorts;
1036     USHORT Port;
1037     USHORT GhostPort;
1038     PUSBHUB_PORT_DATA PortData;
1039     PDEVICE_OBJECT PdoDevice;
1040     PUSBHUB_PORT_PDO_EXTENSION PdoExtension;
1041     PUSBHUB_PORT_PDO_EXTENSION pdoExtension;
1042     NTSTATUS NtStatus;
1043     PVOID SerialNumber;
1044     PVOID DeviceHandle;
1045     USB_PORT_STATUS UsbPortStatus;
1046     PLIST_ENTRY Entry;
1047     ULONG Length;
1048 
1049     DPRINT_ENUM("USBH_FdoQueryBusRelations: HubFlags - %lX\n",
1050                 HubExtension->HubFlags);
1051 
1052     if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED))
1053     {
1054        Status = STATUS_INVALID_DEVICE_STATE;
1055        goto RelationsWorker;
1056     }
1057 
1058     if (!HubExtension->HubDescriptor)
1059     {
1060         Status = STATUS_UNSUCCESSFUL;
1061         goto RelationsWorker;
1062     }
1063 
1064     if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION))
1065     {
1066         DPRINT_ENUM("USBH_FdoQueryBusRelations: Skip enumeration\n");
1067         goto RelationsWorker;
1068     }
1069 
1070     InterlockedIncrement(&HubExtension->PendingRequestCount);
1071 
1072     KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
1073                           Executive,
1074                           KernelMode,
1075                           FALSE,
1076                           NULL);
1077 
1078     NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts;
1079     DPRINT_ENUM("USBH_FdoQueryBusRelations: NumberPorts - %x\n", NumberPorts);
1080 
1081     Length = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
1082              NumberPorts * sizeof(PDEVICE_OBJECT);
1083 
1084     if (Irp->IoStatus.Information)
1085     {
1086         DPRINT1("FIXME: leaking old bus relations\n");
1087     }
1088 
1089     DeviceRelations = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG);
1090 
1091     if (!DeviceRelations)
1092     {
1093         HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED;
1094 
1095         KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
1096                            LOW_REALTIME_PRIORITY,
1097                            1,
1098                            FALSE);
1099 
1100         if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1101         {
1102             KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE);
1103         }
1104 
1105         Status = STATUS_INSUFFICIENT_RESOURCES;
1106         goto RelationsWorker;
1107     }
1108 
1109     RtlZeroMemory(DeviceRelations, Length);
1110 
1111     DeviceRelations->Count = 0;
1112 
1113 EnumStart:
1114 
1115     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING)
1116     {
1117         HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED;
1118 
1119         KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
1120                            LOW_REALTIME_PRIORITY,
1121                            1,
1122                            FALSE);
1123 
1124         if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1125         {
1126             KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE);
1127         }
1128 
1129         Status = STATUS_SUCCESS;
1130         goto RelationsWorker;
1131     }
1132 
1133     HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_ENUM_POST_RECOVER;
1134 
1135     for (Port = 1; Port <= NumberPorts; Port++)
1136     {
1137         PortData = &HubExtension->PortData[Port - 1];
1138 
1139         if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED)
1140         {
1141             continue;
1142         }
1143 
1144         Status = USBH_SyncGetPortStatus(HubExtension,
1145                                         Port,
1146                                         &PortData->PortStatus,
1147                                         sizeof(USB_PORT_STATUS_AND_CHANGE));
1148 
1149         if (!NT_SUCCESS(Status))
1150         {
1151             DPRINT_ENUM("USBH_FdoQueryBusRelations: Status - %X\n", Status);
1152             HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
1153             DeviceRelations->Count = 0;
1154             goto EnumStart;
1155         }
1156 
1157         DPRINT_ENUM("USBH_FdoQueryBusRelations: Port - %x, ConnectStatus - %x\n",
1158                     Port,
1159                     PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus);
1160 
1161         PdoDevice = PortData->DeviceObject;
1162 
1163         if (PortData->DeviceObject)
1164         {
1165             PdoExtension = PdoDevice->DeviceExtension;
1166 
1167             if (PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT)
1168             {
1169                 PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus = 1;
1170             }
1171         }
1172 
1173         if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED)
1174         {
1175             DPRINT1("USBH_FdoQueryBusRelations: DbgBreakPoint() \n");
1176             DbgBreakPoint();
1177         }
1178 
1179         if (!PortData->PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus)
1180         {
1181             if (PdoDevice)
1182             {
1183                 PdoExtension = PdoDevice->DeviceExtension;
1184 
1185                 PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING;
1186                 PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT;
1187 
1188                 SerialNumber = InterlockedExchangePointer((PVOID)&PdoExtension->SerialNumber,
1189                                                           NULL);
1190 
1191                 if (SerialNumber)
1192                 {
1193                     ExFreePoolWithTag(SerialNumber, USB_HUB_TAG);
1194                 }
1195 
1196                 DeviceHandle = InterlockedExchangePointer(&PdoExtension->DeviceHandle,
1197                                                           NULL);
1198 
1199                 if (DeviceHandle)
1200                 {
1201                     USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
1202                     USBH_SyncDisablePort(HubExtension, Port);
1203                 }
1204             }
1205 
1206             PortData->DeviceObject = NULL;
1207             PortData->ConnectionStatus = NoDeviceConnected;
1208             continue;
1209         }
1210 
1211         if (PdoDevice)
1212         {
1213             ObReferenceObject(PdoDevice);
1214 
1215             PdoDevice->Flags |= DO_POWER_PAGABLE;
1216             PdoDevice->Flags &= ~DO_DEVICE_INITIALIZING;
1217 
1218             DeviceRelations->Objects[DeviceRelations->Count++] = PdoDevice;
1219 
1220             PdoExtension = PdoDevice->DeviceExtension;
1221             PdoExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D1_OR_D2;
1222 
1223             continue;
1224         }
1225 
1226         USBH_Wait(100);
1227 
1228         NtStatus = USBH_SyncResetPort(HubExtension, Port);
1229 
1230         if (!NT_SUCCESS(NtStatus))
1231         {
1232             if (HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)
1233             {
1234                 PortData->DeviceObject = NULL;
1235                 PortData->ConnectionStatus = NoDeviceConnected;
1236                 continue;
1237             }
1238         }
1239         else
1240         {
1241             NtStatus = USBH_SyncGetPortStatus(HubExtension,
1242                                               Port,
1243                                               &PortData->PortStatus,
1244                                               sizeof(USB_PORT_STATUS_AND_CHANGE));
1245 
1246             UsbPortStatus = PortData->PortStatus.PortStatus;
1247 
1248             if (NT_SUCCESS(NtStatus))
1249             {
1250                 ULONG ix = 0;
1251 
1252                 for (NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix);
1253                      !NT_SUCCESS(NtStatus);
1254                      NtStatus = USBH_CreateDevice(HubExtension, Port, UsbPortStatus, ix))
1255                 {
1256                     USBH_Wait(500);
1257 
1258                     if (ix >= 2)
1259                     {
1260                         break;
1261                     }
1262 
1263                     if (PortData->DeviceObject)
1264                     {
1265                         IoDeleteDevice(PortData->DeviceObject);
1266                         PortData->DeviceObject = NULL;
1267                         PortData->ConnectionStatus = NoDeviceConnected;
1268                     }
1269 
1270                     USBH_SyncResetPort(HubExtension, Port);
1271 
1272                     ix++;
1273                 }
1274 
1275                 if (NT_SUCCESS(NtStatus))
1276                 {
1277                     PdoExtension = PortData->DeviceObject->DeviceExtension;
1278 
1279                     if (!(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_LOW_SPEED) &&
1280                         !(PdoExtension->PortPdoFlags & USBHUB_PDO_FLAG_PORT_HIGH_SPEED) &&
1281                         !(HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB))
1282                     {
1283                         DPRINT1("USBH_FdoQueryBusRelations: FIXME USBH_DeviceIs2xDualMode()\n");
1284 
1285                         if (0)//USBH_DeviceIs2xDualMode(PdoExtension))
1286                         {
1287                             PdoExtension->PortPdoFlags |= USBHUB_PDO_FLAG_HS_USB1_DUALMODE;
1288                         }
1289                     }
1290 
1291                     ObReferenceObject(PortData->DeviceObject);
1292 
1293                     DeviceRelations->Objects[DeviceRelations->Count] = PortData->DeviceObject;
1294 
1295                     PortData->DeviceObject->Flags |= DO_POWER_PAGABLE;
1296                     PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1297 
1298                     DeviceRelations->Count++;
1299 
1300                     PortData->ConnectionStatus = DeviceConnected;
1301 
1302                     continue;
1303                 }
1304             }
1305         }
1306 
1307         PortData->ConnectionStatus = DeviceFailedEnumeration;
1308 
1309         if (NT_ERROR(USBH_SyncDisablePort(HubExtension, Port)))
1310         {
1311             HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
1312         }
1313 
1314         if (PortData->DeviceObject)
1315         {
1316             ObReferenceObject(PortData->DeviceObject);
1317             PortData->DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1318             DeviceRelations->Objects[DeviceRelations->Count++] = PortData->DeviceObject;
1319         }
1320     }
1321 
1322     HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_NOT_ENUMERATED;
1323 
1324     KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
1325                        LOW_REALTIME_PRIORITY,
1326                        1,
1327                        FALSE);
1328 
1329     if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1330     {
1331         KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE);
1332     }
1333 
1334 RelationsWorker:
1335 
1336     Irp->IoStatus.Status = Status;
1337 
1338     if (!NT_SUCCESS(Status))
1339     {
1340         //Irp->IoStatus.Information = 0;
1341 
1342         if (DeviceRelations)
1343         {
1344             ExFreePoolWithTag(DeviceRelations, USB_HUB_TAG);
1345         }
1346 
1347         USBH_CompleteIrp(Irp, Status);
1348 
1349         return Status;
1350     }
1351 
1352     KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &OldIrql);
1353 
1354     if (DeviceRelations && DeviceRelations->Count)
1355     {
1356         for (Port = 0; Port < DeviceRelations->Count; Port++)
1357         {
1358             PdoDevice = DeviceRelations->Objects[Port];
1359             Entry = HubExtension->PdoList.Flink;
1360 
1361             while (Entry != &HubExtension->PdoList)
1362             {
1363                 pdoExtension = CONTAINING_RECORD(Entry,
1364                                                  USBHUB_PORT_PDO_EXTENSION,
1365                                                  PortLink);
1366 
1367                 if (pdoExtension == PdoDevice->DeviceExtension)
1368                 {
1369                     PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_GHOST_DEVICE;
1370                     goto PortNext;
1371                 }
1372 
1373                 Entry = Entry->Flink;
1374             }
1375 
1376             PdoExt(PdoDevice)->EnumFlags |= USBHUB_ENUM_FLAG_DEVICE_PRESENT;
1377 
1378     PortNext:;
1379         }
1380 
1381         for (Port = 0; Port < DeviceRelations->Count; Port++)
1382         {
1383             PdoDevice = DeviceRelations->Objects[Port];
1384 
1385             if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE)
1386             {
1387                 for (GhostPort = Port;
1388                      GhostPort < DeviceRelations->Count;
1389                      GhostPort++)
1390                 {
1391                     DeviceRelations->Objects[GhostPort] =
1392                     DeviceRelations->Objects[GhostPort + 1];
1393                 }
1394 
1395                 ObDereferenceObject(PdoDevice);
1396 
1397                 DeviceRelations->Count--;
1398 
1399                 if (PdoExt(PdoDevice)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT)
1400                 {
1401                     PdoExt(PdoDevice)->EnumFlags &= ~USBHUB_ENUM_FLAG_GHOST_DEVICE;
1402                 }
1403             }
1404         }
1405     }
1406 
1407     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1408 
1409     InitializeListHead(&GhostPdoList);
1410     PdoList = &HubExtension->PdoList;
1411 
1412     while (!IsListEmpty(PdoList))
1413     {
1414         Entry = RemoveHeadList(PdoList);
1415 
1416         PdoExtension = CONTAINING_RECORD(Entry,
1417                                          USBHUB_PORT_PDO_EXTENSION,
1418                                          PortLink);
1419 
1420         PdoExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT;
1421 
1422         if (PdoExtension->EnumFlags & USBHUB_ENUM_FLAG_GHOST_DEVICE)
1423         {
1424             InsertTailList(&GhostPdoList, &PdoExtension->PortLink);
1425         }
1426     }
1427 
1428     KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, OldIrql);
1429 
1430     while (!IsListEmpty(&GhostPdoList))
1431     {
1432         Entry = RemoveHeadList(&GhostPdoList);
1433 
1434         PdoExtension = CONTAINING_RECORD(Entry,
1435                                          USBHUB_PORT_PDO_EXTENSION,
1436                                          PortLink);
1437 
1438         IoDeleteDevice(PdoExtension->Common.SelfDevice);
1439     }
1440 
1441     return USBH_PassIrp(HubExtension->LowerDevice, Irp);
1442 }
1443 
1444 NTSTATUS
1445 NTAPI
1446 USBH_FdoStopDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
1447                    IN PIRP Irp)
1448 {
1449     DPRINT1("USBH_FdoStopDevice: UNIMPLEMENTED. FIXME\n");
1450     DbgBreakPoint();
1451     return STATUS_SUCCESS;
1452 }
1453 
1454 NTSTATUS
1455 NTAPI
1456 USBH_FdoRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
1457                      IN PIRP Irp)
1458 {
1459     PUSB_HUB_DESCRIPTOR HubDescriptor;
1460     PUSBHUB_PORT_DATA PortData;
1461     USHORT NumPorts;
1462     USHORT ix;
1463     PDEVICE_OBJECT PortDevice;
1464     PUSBHUB_PORT_PDO_EXTENSION PortExtension;
1465     NTSTATUS Status;
1466 
1467     DPRINT("USBH_FdoRemoveDevice: HubExtension - %p\n", HubExtension);
1468 
1469     HubDescriptor = HubExtension->HubDescriptor;
1470 
1471     if (HubDescriptor && HubExtension->PortData)
1472     {
1473         NumPorts = HubDescriptor->bNumberOfPorts;
1474 
1475         for (ix = 0; ix < NumPorts; ++ix)
1476         {
1477             PortData = HubExtension->PortData + ix;
1478 
1479             PortDevice = PortData->DeviceObject;
1480 
1481             if (PortDevice)
1482             {
1483                 PortData->PortStatus.AsUlong32 = 0;
1484                 PortData->DeviceObject = NULL;
1485 
1486                 PortExtension = PortDevice->DeviceExtension;
1487                 PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT;
1488 
1489                 USBH_PdoRemoveDevice(PortExtension, HubExtension);
1490             }
1491         }
1492     }
1493 
1494     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)
1495     {
1496         USBH_FdoCleanup(HubExtension);
1497     }
1498 
1499     if (HubExtension->PortData)
1500     {
1501         ExFreePoolWithTag(HubExtension->PortData, USB_HUB_TAG);
1502         HubExtension->PortData = NULL;
1503     }
1504 
1505     DPRINT1("USBH_FdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n");
1506 
1507     Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
1508 
1509     IoDetachDevice(HubExtension->LowerDevice);
1510     IoDeleteDevice(HubExtension->Common.SelfDevice);
1511 
1512     return Status;
1513 }
1514 
1515 VOID
1516 NTAPI
1517 USBH_FdoSurpriseRemoveDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
1518                              IN PIRP Irp)
1519 {
1520     PUSBHUB_PORT_PDO_EXTENSION PortExtension;
1521     PUSBHUB_PORT_DATA PortData;
1522     ULONG NumberPorts;
1523     ULONG Port;
1524 
1525     DPRINT("USBH_FdoSurpriseRemoveDevice: HubExtension - %p, Irp - %p\n",
1526            HubExtension,
1527            Irp);
1528 
1529     if (!HubExtension->PortData ||
1530         !HubExtension->HubDescriptor)
1531     {
1532         return;
1533     }
1534 
1535     PortData = HubExtension->PortData;
1536     NumberPorts = HubExtension->HubDescriptor->bNumberOfPorts;
1537 
1538     for (Port = 0; Port < NumberPorts; Port++)
1539     {
1540         if (PortData[Port].DeviceObject)
1541         {
1542             PortExtension = PdoExt(PortData[Port].DeviceObject);
1543             PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DELETE_PENDING;
1544             PortExtension->EnumFlags &= ~USBHUB_ENUM_FLAG_DEVICE_PRESENT;
1545 
1546             PortData[Port].DeviceObject = NULL;
1547             PortData[Port].ConnectionStatus = NoDeviceConnected;
1548         }
1549     }
1550 }
1551 
1552 NTSTATUS
1553 NTAPI
1554 USBH_PdoQueryId(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
1555                 IN PIRP Irp)
1556 {
1557     ULONG IdType;
1558     WCHAR Buffer[200];
1559     PWCHAR EndBuffer;
1560     size_t Remaining = sizeof(Buffer);
1561     size_t Length;
1562     PWCHAR Id = NULL;
1563     NTSTATUS Status = STATUS_SUCCESS;
1564     PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
1565     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
1566 
1567     IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
1568     DeviceDescriptor = &PortExtension->DeviceDescriptor;
1569     InterfaceDescriptor = &PortExtension->InterfaceDescriptor;
1570 
1571     RtlZeroMemory(Buffer, sizeof(Buffer));
1572 
1573     switch (IdType)
1574     {
1575         case BusQueryDeviceID:
1576             DPRINT("USBH_PdoQueryId: BusQueryDeviceID\n");
1577 
1578             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)
1579             {
1580                 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n");
1581                 RtlStringCbPrintfExW(Buffer,
1582                                      Remaining,
1583                                      NULL,
1584                                      &Remaining,
1585                                      0,
1586                                      L"USB\\Vid_0000&Pid_0000");
1587             }
1588             else
1589             {
1590                 RtlStringCbPrintfExW(Buffer,
1591                                      Remaining,
1592                                      NULL,
1593                                      &Remaining,
1594                                      0,
1595                                      L"USB\\Vid_%04x&Pid_%04x",
1596                                      DeviceDescriptor->idVendor,
1597                                      DeviceDescriptor->idProduct);
1598             }
1599 
1600             Length = sizeof(Buffer) - (Remaining - sizeof(UNICODE_NULL));
1601 
1602             Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
1603 
1604             if (!Id)
1605             {
1606                 break;
1607             }
1608 
1609             RtlCopyMemory(Id, Buffer, Length);
1610             DPRINT("USBH_PdoQueryId: BusQueryDeviceID - %S\n", Id);
1611             break;
1612 
1613         case BusQueryHardwareIDs:
1614             DPRINT("USBH_PdoQueryId: BusQueryHardwareIDs\n");
1615 
1616             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)
1617             {
1618                 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n");
1619 
1620                 RtlStringCbPrintfExW(Buffer,
1621                                      Remaining,
1622                                      NULL,
1623                                      &Remaining,
1624                                      0,
1625                                      L"USB\\UNKNOWN");
1626             }
1627             else
1628             {
1629                 RtlStringCbPrintfExW(Buffer,
1630                                      Remaining,
1631                                      &EndBuffer,
1632                                      &Remaining,
1633                                      0,
1634                                      L"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
1635                                      DeviceDescriptor->idVendor,
1636                                      DeviceDescriptor->idProduct,
1637                                      DeviceDescriptor->bcdDevice);
1638 
1639                 EndBuffer++;
1640                 Remaining -= sizeof(UNICODE_NULL);
1641 
1642                 RtlStringCbPrintfExW(EndBuffer,
1643                                      Remaining,
1644                                      NULL,
1645                                      &Remaining,
1646                                      0,
1647                                      L"USB\\Vid_%04x&Pid_%04x",
1648                                      DeviceDescriptor->idVendor,
1649                                      DeviceDescriptor->idProduct);
1650             }
1651 
1652             Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL));
1653 
1654             Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
1655 
1656             if (!Id)
1657             {
1658                 break;
1659             }
1660 
1661             RtlCopyMemory(Id, Buffer, Length);
1662 
1663             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)
1664             {
1665                 DPRINT("USBH_PdoQueryId: BusQueryHardwareID - %S\n", Id);
1666             }
1667             else
1668             {
1669                 USBHUB_DumpingIDs(Id);
1670             }
1671 
1672             break;
1673 
1674         case BusQueryCompatibleIDs:
1675             DPRINT("USBH_PdoQueryId: BusQueryCompatibleIDs\n");
1676 
1677             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)
1678             {
1679                 DPRINT("USBH_PdoQueryId: USBHUB_PDO_FLAG_INIT_PORT_FAILED\n");
1680 
1681                 RtlStringCbPrintfExW(Buffer,
1682                                      Remaining,
1683                                      NULL,
1684                                      &Remaining,
1685                                      0,
1686                                      L"USB\\UNKNOWN");
1687             }
1688             else if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_MULTI_INTERFACE)
1689             {
1690                 RtlStringCbPrintfExW(Buffer,
1691                                      Remaining,
1692                                      &EndBuffer,
1693                                      &Remaining,
1694                                      0,
1695                                      L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
1696                                      InterfaceDescriptor->bInterfaceClass,
1697                                      InterfaceDescriptor->bInterfaceSubClass,
1698                                      InterfaceDescriptor->bInterfaceProtocol);
1699 
1700                 EndBuffer++;
1701                 Remaining -= sizeof(UNICODE_NULL);
1702 
1703                 RtlStringCbPrintfExW(EndBuffer,
1704                                      Remaining,
1705                                      &EndBuffer,
1706                                      &Remaining,
1707                                      0,
1708                                      L"USB\\DevClass_%02x&SubClass_%02x",
1709                                      InterfaceDescriptor->bInterfaceClass,
1710                                      InterfaceDescriptor->bInterfaceSubClass);
1711 
1712                 EndBuffer++;
1713                 Remaining -= sizeof(UNICODE_NULL);
1714 
1715                 RtlStringCbPrintfExW(EndBuffer,
1716                                      Remaining,
1717                                      &EndBuffer,
1718                                      &Remaining,
1719                                      0,
1720                                      L"USB\\DevClass_%02x",
1721                                      InterfaceDescriptor->bInterfaceClass);
1722 
1723                 EndBuffer++;
1724                 Remaining -= sizeof(UNICODE_NULL);
1725 
1726                 RtlStringCbPrintfExW(EndBuffer,
1727                                      Remaining,
1728                                      NULL,
1729                                      &Remaining,
1730                                      0,
1731                                      L"USB\\COMPOSITE");
1732             }
1733             else
1734             {
1735                 RtlStringCbPrintfExW(Buffer,
1736                                      Remaining,
1737                                      &EndBuffer,
1738                                      &Remaining,
1739                                      0,
1740                                      L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
1741                                      InterfaceDescriptor->bInterfaceClass,
1742                                      InterfaceDescriptor->bInterfaceSubClass,
1743                                      InterfaceDescriptor->bInterfaceProtocol);
1744 
1745                 EndBuffer++;
1746                 Remaining -= sizeof(UNICODE_NULL);
1747 
1748                 RtlStringCbPrintfExW(EndBuffer,
1749                                      Remaining,
1750                                      &EndBuffer,
1751                                      &Remaining,
1752                                      0,
1753                                      L"USB\\Class_%02x&SubClass_%02x",
1754                                      InterfaceDescriptor->bInterfaceClass,
1755                                      InterfaceDescriptor->bInterfaceSubClass);
1756 
1757                 EndBuffer++;
1758                 Remaining -= sizeof(UNICODE_NULL);
1759 
1760                 RtlStringCbPrintfExW(EndBuffer,
1761                                      Remaining,
1762                                      NULL,
1763                                      &Remaining,
1764                                      0,
1765                                      L"USB\\Class_%02x",
1766                                      InterfaceDescriptor->bInterfaceClass);
1767             }
1768 
1769             Length = sizeof(Buffer) - (Remaining - 2 * sizeof(UNICODE_NULL));
1770 
1771             Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
1772 
1773             if (!Id)
1774             {
1775                 break;
1776             }
1777 
1778             RtlCopyMemory(Id, Buffer, Length);
1779 
1780             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED)
1781             {
1782                 DPRINT("USBH_PdoQueryId: BusQueryCompatibleID - %S\n", Id);
1783             }
1784             else
1785             {
1786                 USBHUB_DumpingIDs(Id);
1787             }
1788 
1789             break;
1790 
1791         case BusQueryInstanceID:
1792             DPRINT("USBH_PdoQueryId: BusQueryInstanceID\n");
1793 
1794             if (PortExtension->SerialNumber)
1795             {
1796                 Id = ExAllocatePoolWithTag(PagedPool,
1797                                            PortExtension->SN_DescriptorLength,
1798                                            USB_HUB_TAG);
1799 
1800                 if (Id)
1801                 {
1802                     RtlZeroMemory(Id, PortExtension->SN_DescriptorLength);
1803 
1804                     RtlCopyMemory(Id,
1805                                   PortExtension->SerialNumber,
1806                                   PortExtension->SN_DescriptorLength);
1807                 }
1808             }
1809             else
1810             {
1811                  Length = sizeof(PortExtension->InstanceID) +
1812                           sizeof(UNICODE_NULL);
1813 
1814                  Id = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
1815 
1816                  if (Id)
1817                  {
1818                      RtlZeroMemory(Id, Length);
1819 
1820                      RtlCopyMemory(Id,
1821                                    PortExtension->InstanceID,
1822                                    sizeof(PortExtension->InstanceID));
1823                  }
1824             }
1825 
1826             DPRINT("USBH_PdoQueryId: BusQueryInstanceID - %S\n", Id);
1827             break;
1828 
1829         default:
1830             DPRINT1("USBH_PdoQueryId: unknown query id type 0x%lx\n", IdType);
1831             return Irp->IoStatus.Status;
1832     }
1833 
1834     Irp->IoStatus.Information = (ULONG_PTR)Id;
1835 
1836     if (!Id)
1837     {
1838         Status = STATUS_INSUFFICIENT_RESOURCES;
1839     }
1840 
1841     return Status;
1842 }
1843 
1844 NTSTATUS
1845 NTAPI
1846 USBH_PdoQueryDeviceText(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
1847                         IN PIRP Irp)
1848 {
1849     PDEVICE_OBJECT DeviceObject;
1850     PIO_STACK_LOCATION IoStack;
1851     DEVICE_TEXT_TYPE DeviceTextType;
1852     USHORT LanguageId;
1853     USHORT DefaultId;
1854     PUSB_STRING_DESCRIPTOR Descriptor;
1855     PWCHAR DeviceText;
1856     UCHAR iProduct = 0;
1857     NTSTATUS Status;
1858     size_t NumSymbols;
1859     size_t Length;
1860 
1861     DPRINT("USBH_PdoQueryDeviceText ... \n");
1862 
1863     DeviceObject = PortExtension->Common.SelfDevice;
1864     IoStack = IoGetCurrentIrpStackLocation(Irp);
1865     DeviceTextType = IoStack->Parameters.QueryDeviceText.DeviceTextType;
1866 
1867     if (DeviceTextType != DeviceTextDescription &&
1868         DeviceTextType != DeviceTextLocationInformation)
1869     {
1870         return Irp->IoStatus.Status;
1871     }
1872 
1873     LanguageId = LANGIDFROMLCID(IoStack->Parameters.QueryDeviceText.LocaleId);
1874     DefaultId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
1875 
1876     if (!LanguageId)
1877     {
1878         LanguageId = DefaultId;
1879     }
1880 
1881     iProduct = PortExtension->DeviceDescriptor.iProduct;
1882 
1883     if (PortExtension->DeviceHandle && iProduct &&
1884         !PortExtension->IgnoringHwSerial &&
1885         !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_INIT_PORT_FAILED))
1886     {
1887         Descriptor = ExAllocatePoolWithTag(NonPagedPool,
1888                                            MAXIMUM_USB_STRING_LENGTH,
1889                                            USB_HUB_TAG);
1890 
1891         if (Descriptor)
1892         {
1893             RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH);
1894 
1895             for (Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId);
1896                  ;
1897                  Status = USBH_CheckDeviceLanguage(DeviceObject, DefaultId))
1898             {
1899                 if (NT_SUCCESS(Status))
1900                 {
1901                     Status = USBH_SyncGetStringDescriptor(DeviceObject,
1902                                                           iProduct,
1903                                                           LanguageId,
1904                                                           Descriptor,
1905                                                           MAXIMUM_USB_STRING_LENGTH,
1906                                                           NULL,
1907                                                           TRUE);
1908 
1909                     if (NT_SUCCESS(Status))
1910                     {
1911                         break;
1912                     }
1913                 }
1914 
1915                 if (LanguageId == DefaultId)
1916                 {
1917                     goto Exit;
1918                 }
1919 
1920                 LanguageId = DefaultId;
1921             }
1922 
1923             if (Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR))
1924             {
1925                 Status = STATUS_UNSUCCESSFUL;
1926             }
1927 
1928             if (NT_SUCCESS(Status))
1929             {
1930                 Length = Descriptor->bLength -
1931                          FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString);
1932 
1933                 DeviceText = ExAllocatePoolWithTag(PagedPool,
1934                                                    Length + sizeof(UNICODE_NULL),
1935                                                    USB_HUB_TAG);
1936 
1937                 if (DeviceText)
1938                 {
1939                     RtlZeroMemory(DeviceText, Length + sizeof(UNICODE_NULL));
1940 
1941                     RtlCopyMemory(DeviceText, Descriptor->bString, Length);
1942 
1943                     Irp->IoStatus.Information = (ULONG_PTR)DeviceText;
1944 
1945                     DPRINT("USBH_PdoQueryDeviceText: Descriptor->bString - %S\n",
1946                            DeviceText);
1947                 }
1948                 else
1949                 {
1950                     Status = STATUS_INSUFFICIENT_RESOURCES;
1951                 }
1952             }
1953 
1954         Exit:
1955 
1956             ExFreePoolWithTag(Descriptor, USB_HUB_TAG);
1957 
1958             if (NT_SUCCESS(Status))
1959             {
1960                 return Status;
1961             }
1962         }
1963         else
1964         {
1965             Status = STATUS_INSUFFICIENT_RESOURCES;
1966         }
1967     }
1968     else
1969     {
1970         Status = STATUS_NOT_SUPPORTED;
1971     }
1972 
1973     if (!GenericUSBDeviceString)
1974     {
1975         return Status;
1976     }
1977 
1978     NumSymbols = wcslen(GenericUSBDeviceString);
1979     Length = (NumSymbols + 1) * sizeof(WCHAR);
1980 
1981     DeviceText = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
1982 
1983     if (!DeviceText)
1984     {
1985         return STATUS_INSUFFICIENT_RESOURCES;
1986     }
1987 
1988     RtlZeroMemory(DeviceText, Length);
1989 
1990     RtlCopyMemory(DeviceText,
1991                   GenericUSBDeviceString,
1992                   NumSymbols * sizeof(WCHAR));
1993 
1994     Irp->IoStatus.Information = (ULONG_PTR)DeviceText;
1995 
1996     return STATUS_SUCCESS;
1997 }
1998 
1999 NTSTATUS
2000 NTAPI
2001 USBH_SymbolicLink(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2002                   IN const GUID * InterfaceClassGuid,
2003                   IN BOOLEAN IsEnable)
2004 {
2005     NTSTATUS Status = STATUS_SUCCESS;
2006     PVOID NameBuffer;
2007 
2008     DPRINT("USBH_SymbolicLink ... \n");
2009 
2010     if (IsEnable)
2011     {
2012         Status = IoRegisterDeviceInterface(PortExtension->Common.SelfDevice,
2013                                            InterfaceClassGuid,
2014                                            NULL,
2015                                            &PortExtension->SymbolicLinkName);
2016 
2017         if (NT_SUCCESS(Status))
2018         {
2019             USBH_SetPdoRegistryParameter(PortExtension->Common.SelfDevice,
2020                                          L"SymbolicName",
2021                                          PortExtension->SymbolicLinkName.Buffer,
2022                                          PortExtension->SymbolicLinkName.Length,
2023                                          REG_SZ,
2024                                          PLUGPLAY_REGKEY_DEVICE);
2025 
2026             Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName,
2027                                                TRUE);
2028         }
2029     }
2030     else
2031     {
2032         NameBuffer = PortExtension->SymbolicLinkName.Buffer;
2033 
2034         if (NameBuffer)
2035         {
2036             Status = IoSetDeviceInterfaceState(&PortExtension->SymbolicLinkName,
2037                                                FALSE);
2038 
2039             ExFreePool(PortExtension->SymbolicLinkName.Buffer);
2040 
2041             PortExtension->SymbolicLinkName.Buffer = NULL;
2042         }
2043     }
2044 
2045     return Status;
2046 }
2047 
2048 NTSTATUS
2049 NTAPI
2050 USBH_RestoreDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2051                    IN BOOLEAN IsKeepDeviceData)
2052 {
2053     PUSBHUB_FDO_EXTENSION HubExtension;
2054     PUSBHUB_PORT_DATA PortData;
2055     NTSTATUS Status;
2056     ULONG ix;
2057 
2058     DPRINT("USBH_RestoreDevice ... \n");
2059 
2060     HubExtension = PortExtension->HubExtension;
2061 
2062     if (!HubExtension)
2063     {
2064         Status = STATUS_UNSUCCESSFUL;
2065         return Status;
2066     }
2067 
2068     ASSERT(PortExtension->PortNumber > 0);
2069     PortData = &HubExtension->PortData[PortExtension->PortNumber - 1];
2070 
2071     if (PortExtension->Common.SelfDevice != PortData->DeviceObject)
2072     {
2073         Status = STATUS_UNSUCCESSFUL;
2074         return Status;
2075     }
2076 
2077     Status = USBH_SyncGetPortStatus(HubExtension,
2078                                     PortExtension->PortNumber,
2079                                     &PortData->PortStatus,
2080                                     sizeof(USB_PORT_STATUS_AND_CHANGE));
2081 
2082     if (NT_SUCCESS(Status))
2083     {
2084         for (ix = 0; ix < 3; ix++)
2085         {
2086             Status = USBH_ResetDevice((PUSBHUB_FDO_EXTENSION)HubExtension,
2087                                       PortExtension->PortNumber,
2088                                       IsKeepDeviceData,
2089                                       ix == 0);
2090 
2091             if (NT_SUCCESS(Status) || Status == STATUS_NO_SUCH_DEVICE)
2092             {
2093                 break;
2094             }
2095 
2096             USBH_Wait(1000);
2097         }
2098     }
2099 
2100     PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_POWER_D3;
2101 
2102     if (NT_SUCCESS(Status))
2103     {
2104         PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_PORT_RESTORE_FAIL;
2105     }
2106     else
2107     {
2108         PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_INIT_PORT_FAILED |
2109                                         USBHUB_PDO_FLAG_PORT_RESTORE_FAIL);
2110     }
2111 
2112     return Status;
2113 }
2114 
2115 NTSTATUS
2116 NTAPI
2117 USBH_PdoStartDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2118                     IN PIRP Irp)
2119 {
2120     PUSBHUB_FDO_EXTENSION HubExtension;
2121     const GUID * Guid;
2122     NTSTATUS Status;
2123 
2124     DPRINT("USBH_PdoStartDevice: PortExtension - %p\n", PortExtension);
2125 
2126     if (!PortExtension->HubExtension &&
2127         PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3)
2128     {
2129         PortExtension->HubExtension = PortExtension->RootHubExtension;
2130     }
2131 
2132     HubExtension = PortExtension->HubExtension;
2133 
2134     if (HubExtension)
2135     {
2136         USBHUB_SetDeviceHandleData(HubExtension,
2137                                    PortExtension->Common.SelfDevice,
2138                                    PortExtension->DeviceHandle);
2139     }
2140 
2141     if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE)
2142     {
2143         Guid = &GUID_DEVINTERFACE_USB_HUB;
2144     }
2145     else
2146     {
2147         Guid = &GUID_DEVINTERFACE_USB_DEVICE;
2148     }
2149 
2150     Status = USBH_SymbolicLink(PortExtension, Guid, TRUE);
2151 
2152     if (NT_SUCCESS(Status))
2153     {
2154         PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REG_DEV_INTERFACE;
2155     }
2156 
2157     if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3)
2158     {
2159         Status = USBH_RestoreDevice(PortExtension, 0);
2160     }
2161 
2162     PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_DEVICE_STARTED;
2163 
2164     PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0;
2165 
2166     DPRINT1("USBH_PdoStartDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n");
2167 
2168     return Status;
2169 }
2170 
2171 NTSTATUS
2172 NTAPI
2173 USBH_PdoRemoveDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2174                      IN PUSBHUB_FDO_EXTENSION HubExtension)
2175 {
2176     NTSTATUS Status = STATUS_SUCCESS;
2177     PDEVICE_OBJECT PortDevice;
2178     PUSBHUB_PORT_PDO_EXTENSION PortExt;
2179     PUSBHUB_PORT_DATA PortData;
2180     PIRP IdleNotificationIrp;
2181     PIRP WakeIrp;
2182     PVOID DeviceHandle;
2183     PDEVICE_OBJECT Pdo;
2184     PVOID SerialNumber;
2185     USHORT Port;
2186     KIRQL Irql;
2187 
2188     DPRINT("USBH_PdoRemoveDevice ... \n");
2189 
2190     PortDevice = PortExtension->Common.SelfDevice;
2191     PortExtension->HubExtension = NULL;
2192 
2193     Port = PortExtension->PortNumber;
2194     ASSERT(Port > 0);
2195 
2196     if (HubExtension &&
2197         HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 &&
2198         (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) != 0)
2199     {
2200         USBH_HubSetD0(HubExtension);
2201     }
2202 
2203     IoAcquireCancelSpinLock(&Irql);
2204     IdleNotificationIrp = PortExtension->IdleNotificationIrp;
2205 
2206     if (IdleNotificationIrp)
2207     {
2208         PortExtension->IdleNotificationIrp = NULL;
2209         PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_IDLE_NOTIFICATION;
2210 
2211         if (IdleNotificationIrp->Cancel)
2212         {
2213             IdleNotificationIrp = NULL;
2214         }
2215 
2216         if (IdleNotificationIrp)
2217         {
2218             IoSetCancelRoutine(IdleNotificationIrp, NULL);
2219         }
2220     }
2221 
2222     WakeIrp = PortExtension->PdoWaitWakeIrp;
2223 
2224     if (WakeIrp)
2225     {
2226         PortExtension->PdoWaitWakeIrp = NULL;
2227         PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_WAIT_WAKE;
2228 
2229         if (WakeIrp->Cancel || !IoSetCancelRoutine(WakeIrp, NULL))
2230         {
2231             WakeIrp = NULL;
2232 
2233             ASSERT(HubExtension);
2234             if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2235             {
2236                 KeSetEvent(&HubExtension->PendingRequestEvent,
2237                            EVENT_INCREMENT,
2238                            FALSE);
2239             }
2240         }
2241     }
2242 
2243     IoReleaseCancelSpinLock(Irql);
2244 
2245     if (IdleNotificationIrp)
2246     {
2247         IdleNotificationIrp->IoStatus.Status = STATUS_CANCELLED;
2248         IoCompleteRequest(IdleNotificationIrp, IO_NO_INCREMENT);
2249     }
2250 
2251     if (WakeIrp)
2252     {
2253         ASSERT(HubExtension);
2254         USBH_CompletePowerIrp(HubExtension, WakeIrp, STATUS_CANCELLED);
2255     }
2256 
2257     PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_POWER_D3;
2258 
2259     if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE)
2260     {
2261         Status = USBH_SymbolicLink(PortExtension, NULL, FALSE);
2262 
2263         if (NT_SUCCESS(Status))
2264         {
2265             PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE;
2266         }
2267     }
2268 
2269     DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
2270                                               NULL);
2271 
2272     if (DeviceHandle)
2273     {
2274         ASSERT(HubExtension);
2275         Status = USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
2276 
2277         if (HubExtension->PortData &&
2278             HubExtension->PortData[Port - 1].DeviceObject == PortDevice)
2279         {
2280             USBH_SyncDisablePort(HubExtension, Port);
2281         }
2282     }
2283 
2284     if (NT_SUCCESS(Status))
2285     {
2286         PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_DEVICE_STARTED;
2287 
2288         if (HubExtension && HubExtension->PortData)
2289         {
2290             PortData = &HubExtension->PortData[Port - 1];
2291 
2292             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_DELETE_PENDING)
2293             {
2294                 Pdo = PortData->DeviceObject;
2295 
2296                 if (Pdo)
2297                 {
2298                     PortData->DeviceObject = NULL;
2299                     PortData->ConnectionStatus = NoDeviceConnected;
2300 
2301                     if (PdoExt(Pdo)->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT)
2302                     {
2303                         PortExt = PdoExt(Pdo);
2304 
2305                         InsertTailList(&HubExtension->PdoList,
2306                                        &PortExt->PortLink);
2307                     }
2308                 }
2309             }
2310         }
2311 
2312         if (!(PortExtension->EnumFlags & USBHUB_ENUM_FLAG_DEVICE_PRESENT) &&
2313             !(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_NOT_CONNECTED))
2314         {
2315             PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_NOT_CONNECTED;
2316 
2317             SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
2318                                                       NULL);
2319 
2320             if (SerialNumber)
2321             {
2322                 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG);
2323             }
2324 
2325             DPRINT1("USBH_PdoRemoveDevice: call IoWMIRegistrationControl UNIMPLEMENTED. FIXME\n");
2326 
2327             if (HubExtension)
2328                 USBHUB_FlushAllTransfers(HubExtension);
2329 
2330             IoDeleteDevice(PortDevice);
2331         }
2332     }
2333 
2334     if (HubExtension)
2335     {
2336         DPRINT("USBH_PdoRemoveDevice: call USBH_CheckIdleDeferred()\n");
2337         USBH_CheckIdleDeferred(HubExtension);
2338     }
2339 
2340     return Status;
2341 }
2342 
2343 NTSTATUS
2344 NTAPI
2345 USBH_PdoStopDevice(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2346                    IN PIRP Irp)
2347 {
2348     DPRINT1("USBH_PdoStopDevice: UNIMPLEMENTED. FIXME\n");
2349     DbgBreakPoint();
2350     return STATUS_SUCCESS;
2351 }
2352 
2353 NTSTATUS
2354 NTAPI
2355 USBH_FdoPnP(IN PUSBHUB_FDO_EXTENSION HubExtension,
2356             IN PIRP Irp,
2357             IN UCHAR Minor)
2358 {
2359     NTSTATUS Status;
2360     PIO_STACK_LOCATION IoStack;
2361     DEVICE_RELATION_TYPE RelationsType;
2362     BOOLEAN IsCheckIdle;
2363 
2364     DPRINT_PNP("USBH_FdoPnP: HubExtension - %p, Irp - %p, Minor - %X\n",
2365                HubExtension,
2366                Irp,
2367                Minor);
2368 
2369     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST &&
2370         (Minor == IRP_MN_REMOVE_DEVICE || Minor == IRP_MN_STOP_DEVICE))
2371     {
2372         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED;
2373     }
2374 
2375     KeWaitForSingleObject(&HubExtension->IdleSemaphore,
2376                           Executive,
2377                           KernelMode,
2378                           FALSE,
2379                           NULL);
2380 
2381     DPRINT_PNP("USBH_FdoPnP: HubFlags - %lX\n", HubExtension->HubFlags);
2382 
2383     if (HubExtension->HubFlags & USBHUB_FDO_FLAG_GOING_IDLE)
2384     {
2385         HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_SUSPENDED;
2386     }
2387 
2388     IoStack = IoGetCurrentIrpStackLocation(Irp);
2389     RelationsType = IoStack->Parameters.QueryDeviceRelations.Type;
2390 
2391     if ((HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0) ||
2392         !(HubExtension->HubFlags & (USBHUB_FDO_FLAG_DEVICE_STOPPED | USBHUB_FDO_FLAG_DEVICE_STARTED)) ||
2393         (Minor == IRP_MN_QUERY_DEVICE_RELATIONS && RelationsType == TargetDeviceRelation))
2394     {
2395         IsCheckIdle = FALSE;
2396     }
2397     else
2398     {
2399         DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n");
2400         IsCheckIdle = TRUE;
2401         USBH_HubSetD0(HubExtension);
2402     }
2403 
2404     switch (Minor)
2405     {
2406         case IRP_MN_START_DEVICE:
2407             DPRINT_PNP("FDO IRP_MN_START_DEVICE\n");
2408             IsCheckIdle = FALSE;
2409             Irp->IoStatus.Status = STATUS_SUCCESS;
2410             Status = USBH_FdoStartDevice(HubExtension, Irp);
2411             break;
2412 
2413         case IRP_MN_QUERY_REMOVE_DEVICE:
2414             DPRINT_PNP("FDO IRP_MN_QUERY_REMOVE_DEVICE\n");
2415             Irp->IoStatus.Status = STATUS_SUCCESS;
2416             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2417             break;
2418 
2419         case IRP_MN_REMOVE_DEVICE:
2420             DPRINT_PNP("FDO IRP_MN_REMOVE_DEVICE\n");
2421             IsCheckIdle = FALSE;
2422             HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED;
2423             Irp->IoStatus.Status = STATUS_SUCCESS;
2424             Status = USBH_FdoRemoveDevice(HubExtension, Irp);
2425             break;
2426 
2427         case IRP_MN_CANCEL_REMOVE_DEVICE:
2428             DPRINT_PNP("FDO IRP_MN_CANCEL_REMOVE_DEVICE\n");
2429             Irp->IoStatus.Status = STATUS_SUCCESS;
2430             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2431             break;
2432 
2433         case IRP_MN_STOP_DEVICE:
2434             DPRINT_PNP("FDO IRP_MN_STOP_DEVICE\n");
2435             IsCheckIdle = FALSE;
2436             Irp->IoStatus.Status = STATUS_SUCCESS;
2437             Status = USBH_FdoStopDevice(HubExtension, Irp);
2438             break;
2439 
2440         case IRP_MN_QUERY_STOP_DEVICE:
2441             DPRINT_PNP("FDO IRP_MN_QUERY_STOP_DEVICE\n");
2442             Irp->IoStatus.Status = STATUS_SUCCESS;
2443             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2444             break;
2445 
2446         case IRP_MN_CANCEL_STOP_DEVICE:
2447             DPRINT_PNP("FDO IRP_MN_CANCEL_STOP_DEVICE\n");
2448             Irp->IoStatus.Status = STATUS_SUCCESS;
2449             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2450             break;
2451 
2452         case IRP_MN_QUERY_DEVICE_RELATIONS:
2453             DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_RELATIONS\n");
2454 
2455             if (RelationsType != BusRelations)
2456             {
2457                 Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2458                 break;
2459             }
2460 
2461             HubExtension->HubFlags |= USBHUB_FDO_FLAG_HUB_BUSY;
2462 
2463             IsCheckIdle = TRUE;
2464             DPRINT_PNP("USBH_FdoPnP: IsCheckIdle - TRUE\n");
2465 
2466             Status = USBH_FdoQueryBusRelations(HubExtension, Irp);
2467 
2468             HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_HUB_BUSY;
2469             break;
2470 
2471         case IRP_MN_QUERY_INTERFACE:
2472             DPRINT_PNP("FDO IRP_MN_QUERY_INTERFACE\n");
2473             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2474             break;
2475 
2476         case IRP_MN_QUERY_CAPABILITIES:
2477             DPRINT_PNP("FDO IRP_MN_QUERY_CAPABILITIES\n");
2478             IoCopyCurrentIrpStackLocationToNext(Irp);
2479 
2480             IoSetCompletionRoutine(Irp,
2481                                    USBH_QueryCapsComplete,
2482                                    HubExtension,
2483                                    TRUE,
2484                                    FALSE,
2485                                    FALSE);
2486 
2487             Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2488             break;
2489 
2490         case IRP_MN_QUERY_RESOURCES:
2491             DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCES\n");
2492             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2493             break;
2494 
2495         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
2496             DPRINT_PNP("FDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
2497             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2498             break;
2499 
2500         case IRP_MN_QUERY_DEVICE_TEXT:
2501             DPRINT_PNP("FDO IRP_MN_QUERY_DEVICE_TEXT\n");
2502             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2503             break;
2504 
2505         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
2506             DPRINT_PNP("FDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
2507             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2508             break;
2509 
2510         case IRP_MN_READ_CONFIG:
2511             DPRINT_PNP("FDO IRP_MN_READ_CONFIG\n");
2512             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2513             break;
2514 
2515         case IRP_MN_WRITE_CONFIG:
2516             DPRINT_PNP("FDO IRP_MN_WRITE_CONFIG\n");
2517             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2518             break;
2519 
2520         case IRP_MN_EJECT:
2521             DPRINT_PNP("FDO IRP_MN_EJECT\n");
2522             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2523             break;
2524 
2525         case IRP_MN_SET_LOCK:
2526             DPRINT_PNP("FDO IRP_MN_SET_LOCK\n");
2527             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2528             break;
2529 
2530         case IRP_MN_QUERY_ID:
2531             DPRINT_PNP("FDO IRP_MN_QUERY_ID\n");
2532             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2533             break;
2534 
2535         case IRP_MN_QUERY_PNP_DEVICE_STATE:
2536             DPRINT_PNP("FDO IRP_MN_QUERY_PNP_DEVICE_STATE\n");
2537 
2538             if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED)
2539             {
2540                 Irp->IoStatus.Information |= PNP_DEVICE_FAILED;
2541             }
2542 
2543             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2544             break;
2545 
2546         case IRP_MN_QUERY_BUS_INFORMATION:
2547             DPRINT_PNP("FDO IRP_MN_QUERY_BUS_INFORMATION\n");
2548             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2549             break;
2550 
2551         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
2552             DPRINT_PNP("FDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
2553             Irp->IoStatus.Status = STATUS_SUCCESS;
2554             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2555             break;
2556 
2557         case IRP_MN_SURPRISE_REMOVAL:
2558             DPRINT_PNP("FDO IRP_MN_SURPRISE_REMOVAL\n");
2559             USBH_FdoSurpriseRemoveDevice(HubExtension, Irp);
2560             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2561             break;
2562 
2563         default:
2564             DPRINT_PNP("FDO unknown IRP_MN_???\n");
2565             Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
2566             break;
2567     }
2568 
2569     KeReleaseSemaphore(&HubExtension->IdleSemaphore,
2570                        LOW_REALTIME_PRIORITY,
2571                        1,
2572                        FALSE);
2573 
2574     if (IsCheckIdle)
2575     {
2576         DPRINT_PNP("USBH_FdoPnP: call USBH_CheckIdleDeferred()\n");
2577         USBH_CheckIdleDeferred(HubExtension);
2578     }
2579 
2580     HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_STATE_CHANGING;
2581 
2582     return Status;
2583 }
2584 
2585 NTSTATUS
2586 NTAPI
2587 USBH_PdoPnP(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2588             IN PIRP Irp,
2589             IN UCHAR Minor,
2590             OUT BOOLEAN * IsCompleteIrp)
2591 {
2592     NTSTATUS Status;
2593     PIO_STACK_LOCATION IoStack;
2594     PPNP_BUS_INFORMATION BusInfo;
2595     PDEVICE_CAPABILITIES DeviceCapabilities;
2596     USHORT Size;
2597     USHORT Version;
2598     PUSBHUB_FDO_EXTENSION HubExtension;
2599     PDEVICE_RELATIONS DeviceRelation;
2600 
2601     DPRINT_PNP("USBH_PdoPnP: PortExtension - %p, Irp - %p, Minor - %X\n",
2602                PortExtension,
2603                Irp,
2604                Minor);
2605 
2606     IoStack = IoGetCurrentIrpStackLocation(Irp);
2607 
2608     *IsCompleteIrp = TRUE;
2609 
2610     switch (Minor)
2611     {
2612         case IRP_MN_START_DEVICE:
2613             DPRINT_PNP("PDO IRP_MN_START_DEVICE\n");
2614             return USBH_PdoStartDevice(PortExtension, Irp);
2615 
2616         case IRP_MN_QUERY_REMOVE_DEVICE:
2617             DPRINT_PNP("PDO IRP_MN_QUERY_REMOVE_DEVICE\n");
2618             return STATUS_SUCCESS;
2619 
2620         case IRP_MN_REMOVE_DEVICE:
2621             DPRINT_PNP("PDO IRP_MN_REMOVE_DEVICE\n");
2622             return USBH_PdoRemoveDevice(PortExtension, PortExtension->HubExtension);
2623 
2624         case IRP_MN_CANCEL_REMOVE_DEVICE:
2625             DPRINT_PNP("PDO IRP_MN_CANCEL_REMOVE_DEVICE\n");
2626             return STATUS_SUCCESS;
2627 
2628         case IRP_MN_STOP_DEVICE:
2629             DPRINT_PNP("PDO IRP_MN_STOP_DEVICE\n");
2630             return USBH_PdoStopDevice(PortExtension, Irp);
2631 
2632         case IRP_MN_QUERY_STOP_DEVICE:
2633             DPRINT_PNP("PDO IRP_MN_QUERY_STOP_DEVICE\n");
2634             return STATUS_SUCCESS;
2635 
2636         case IRP_MN_CANCEL_STOP_DEVICE:
2637             DPRINT_PNP("PDO IRP_MN_CANCEL_STOP_DEVICE\n");
2638             return STATUS_SUCCESS;
2639 
2640         case IRP_MN_QUERY_DEVICE_RELATIONS:
2641             DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_RELATIONS\n");
2642 
2643             if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
2644             {
2645                 return Irp->IoStatus.Status;
2646             }
2647 
2648             DeviceRelation = ExAllocatePoolWithTag(PagedPool,
2649                                                    sizeof(DEVICE_RELATIONS),
2650                                                    USB_HUB_TAG);
2651 
2652             if (DeviceRelation)
2653             {
2654                 RtlZeroMemory(DeviceRelation, sizeof(DEVICE_RELATIONS));
2655 
2656                 DeviceRelation->Count = 1;
2657                 DeviceRelation->Objects[0] = PortExtension->Common.SelfDevice;
2658 
2659                 ObReferenceObject(DeviceRelation->Objects[0]);
2660 
2661                 Status = STATUS_SUCCESS;
2662             }
2663             else
2664             {
2665                 Status = STATUS_INSUFFICIENT_RESOURCES;
2666             }
2667 
2668             Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
2669             break;
2670 
2671         case IRP_MN_QUERY_INTERFACE:
2672             DPRINT_PNP("PDO IRP_MN_QUERY_INTERFACE\n");
2673 
2674             *IsCompleteIrp = 0;
2675 
2676             if (IsEqualGUIDAligned(IoStack->Parameters.QueryInterface.InterfaceType,
2677                                    &USB_BUS_INTERFACE_USBDI_GUID))
2678             {
2679                 IoStack->Parameters.QueryInterface.InterfaceSpecificData = PortExtension->DeviceHandle;
2680             }
2681 
2682             HubExtension = PortExtension->HubExtension;
2683 
2684             if (!HubExtension)
2685             {
2686                 HubExtension = PortExtension->RootHubExtension;
2687             }
2688 
2689             Status = USBH_PassIrp(HubExtension->RootHubPdo, Irp);
2690             break;
2691 
2692         case IRP_MN_QUERY_CAPABILITIES:
2693             DPRINT_PNP("PDO IRP_MN_QUERY_CAPABILITIES\n");
2694 
2695             DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
2696 
2697             Size = DeviceCapabilities->Size;
2698             Version = DeviceCapabilities->Version;
2699 
2700             RtlCopyMemory(DeviceCapabilities,
2701                           &PortExtension->Capabilities,
2702                           sizeof(DEVICE_CAPABILITIES));
2703 
2704             DeviceCapabilities->Size = Size;
2705             DeviceCapabilities->Version = Version;
2706 
2707             /* All devices connected to a hub are removable */
2708             DeviceCapabilities->Removable = 1;
2709 
2710             Status = STATUS_SUCCESS;
2711             break;
2712 
2713         case IRP_MN_QUERY_RESOURCES:
2714             DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCES\n");
2715             Status = Irp->IoStatus.Status;
2716             break;
2717 
2718         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
2719             DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
2720             PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_ENUMERATED;
2721 
2722             /* FIXME HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Enum\USB\
2723                Vid_????&Pid_????\????????????\Device Parameters\
2724                if (ExtPropDescSemaphore)
2725             */
2726 
2727             Status = STATUS_SUCCESS;
2728             break;
2729 
2730         case IRP_MN_QUERY_DEVICE_TEXT:
2731             DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_TEXT\n");
2732             return USBH_PdoQueryDeviceText(PortExtension, Irp);
2733 
2734         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
2735             DPRINT_PNP("PDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
2736             Status = Irp->IoStatus.Status;
2737             break;
2738 
2739         case IRP_MN_READ_CONFIG:
2740             DPRINT_PNP("PDO IRP_MN_READ_CONFIG\n");
2741             DbgBreakPoint();
2742             Status = Irp->IoStatus.Status;
2743             break;
2744 
2745         case IRP_MN_WRITE_CONFIG:
2746             DPRINT_PNP("PDO IRP_MN_WRITE_CONFIG\n");
2747             DbgBreakPoint();
2748             Status = Irp->IoStatus.Status;
2749             break;
2750 
2751         case IRP_MN_EJECT:
2752             DPRINT_PNP("PDO IRP_MN_EJECT\n");
2753             DbgBreakPoint();
2754             Status = Irp->IoStatus.Status;
2755             break;
2756 
2757         case IRP_MN_SET_LOCK:
2758             DPRINT_PNP("PDO IRP_MN_SET_LOCK\n");
2759             DbgBreakPoint();
2760             Status = Irp->IoStatus.Status;
2761             break;
2762 
2763         case IRP_MN_QUERY_ID:
2764             DPRINT_PNP("PDO IRP_MN_QUERY_ID\n");
2765             return USBH_PdoQueryId(PortExtension, Irp);
2766 
2767         case IRP_MN_QUERY_PNP_DEVICE_STATE:
2768             DPRINT_PNP("PDO IRP_MN_QUERY_PNP_DEVICE_STATE\n");
2769             if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_INSUFFICIENT_PWR |
2770                                                USBHUB_PDO_FLAG_OVERCURRENT_PORT |
2771                                                USBHUB_PDO_FLAG_PORT_RESTORE_FAIL |
2772                                                USBHUB_PDO_FLAG_INIT_PORT_FAILED))
2773             {
2774                 Irp->IoStatus.Information |= PNP_DEVICE_FAILED;
2775             }
2776 
2777             Status = STATUS_SUCCESS;
2778             break;
2779 
2780         case IRP_MN_QUERY_BUS_INFORMATION:
2781             DPRINT_PNP("PDO IRP_MN_QUERY_BUS_INFORMATION\n");
2782 
2783             BusInfo = ExAllocatePoolWithTag(PagedPool,
2784                                             sizeof(PNP_BUS_INFORMATION),
2785                                             USB_HUB_TAG);
2786 
2787             if (!BusInfo)
2788             {
2789                 return STATUS_INSUFFICIENT_RESOURCES;
2790             }
2791 
2792             RtlZeroMemory(BusInfo, sizeof(PNP_BUS_INFORMATION));
2793 
2794             RtlCopyMemory(&BusInfo->BusTypeGuid,
2795                           &GUID_BUS_TYPE_USB,
2796                           sizeof(BusInfo->BusTypeGuid));
2797 
2798             BusInfo->LegacyBusType = PNPBus;
2799             BusInfo->BusNumber = 0;
2800 
2801             Irp->IoStatus.Information = (ULONG_PTR)BusInfo;
2802             Status = STATUS_SUCCESS;
2803             break;
2804 
2805         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
2806             DPRINT_PNP("PDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
2807             DbgBreakPoint();
2808             Status = Irp->IoStatus.Status;
2809             break;
2810 
2811         case IRP_MN_SURPRISE_REMOVAL:
2812             DPRINT_PNP("PDO IRP_MN_SURPRISE_REMOVAL\n");
2813             if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE)
2814             {
2815                 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE);
2816 
2817                 if (NT_SUCCESS(Status))
2818                 {
2819                     PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE;
2820                 }
2821             }
2822 
2823             Status = STATUS_SUCCESS;
2824             break;
2825 
2826         default:
2827             DPRINT_PNP("PDO unknown IRP_MN_???\n");
2828             Status = Irp->IoStatus.Status;
2829             break;
2830     }
2831 
2832     return Status;
2833 }
2834