[USBHUB_NEW] Support NULL HubExtension in USBH_PdoRemoveDevice.
[reactos.git] / drivers / usb / usbhub_new / pnp.c
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 Status = STATUS_SUCCESS;
2708 break;
2709
2710 case IRP_MN_QUERY_RESOURCES:
2711 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCES\n");
2712 Status = Irp->IoStatus.Status;
2713 break;
2714
2715 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
2716 DPRINT_PNP("PDO IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
2717 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_ENUMERATED;
2718
2719 /* FIXME HKEY_LOCAL_MACHINE\SYSTEM\ControlSetXXX\Enum\USB\
2720 Vid_????&Pid_????\????????????\Device Parameters\
2721 if (ExtPropDescSemaphore)
2722 */
2723
2724 Status = STATUS_SUCCESS;
2725 break;
2726
2727 case IRP_MN_QUERY_DEVICE_TEXT:
2728 DPRINT_PNP("PDO IRP_MN_QUERY_DEVICE_TEXT\n");
2729 return USBH_PdoQueryDeviceText(PortExtension, Irp);
2730
2731 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
2732 DPRINT_PNP("PDO IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
2733 Status = Irp->IoStatus.Status;
2734 break;
2735
2736 case IRP_MN_READ_CONFIG:
2737 DPRINT_PNP("PDO IRP_MN_READ_CONFIG\n");
2738 DbgBreakPoint();
2739 Status = Irp->IoStatus.Status;
2740 break;
2741
2742 case IRP_MN_WRITE_CONFIG:
2743 DPRINT_PNP("PDO IRP_MN_WRITE_CONFIG\n");
2744 DbgBreakPoint();
2745 Status = Irp->IoStatus.Status;
2746 break;
2747
2748 case IRP_MN_EJECT:
2749 DPRINT_PNP("PDO IRP_MN_EJECT\n");
2750 DbgBreakPoint();
2751 Status = Irp->IoStatus.Status;
2752 break;
2753
2754 case IRP_MN_SET_LOCK:
2755 DPRINT_PNP("PDO IRP_MN_SET_LOCK\n");
2756 DbgBreakPoint();
2757 Status = Irp->IoStatus.Status;
2758 break;
2759
2760 case IRP_MN_QUERY_ID:
2761 DPRINT_PNP("PDO IRP_MN_QUERY_ID\n");
2762 return USBH_PdoQueryId(PortExtension, Irp);
2763
2764 case IRP_MN_QUERY_PNP_DEVICE_STATE:
2765 DPRINT_PNP("PDO IRP_MN_QUERY_PNP_DEVICE_STATE\n");
2766 if (PortExtension->PortPdoFlags & (USBHUB_PDO_FLAG_INSUFFICIENT_PWR |
2767 USBHUB_PDO_FLAG_OVERCURRENT_PORT |
2768 USBHUB_PDO_FLAG_PORT_RESTORE_FAIL |
2769 USBHUB_PDO_FLAG_INIT_PORT_FAILED))
2770 {
2771 Irp->IoStatus.Information |= PNP_DEVICE_FAILED;
2772 }
2773
2774 Status = STATUS_SUCCESS;
2775 break;
2776
2777 case IRP_MN_QUERY_BUS_INFORMATION:
2778 DPRINT_PNP("PDO IRP_MN_QUERY_BUS_INFORMATION\n");
2779
2780 BusInfo = ExAllocatePoolWithTag(PagedPool,
2781 sizeof(PNP_BUS_INFORMATION),
2782 USB_HUB_TAG);
2783
2784 if (!BusInfo)
2785 {
2786 return STATUS_INSUFFICIENT_RESOURCES;
2787 }
2788
2789 RtlZeroMemory(BusInfo, sizeof(PNP_BUS_INFORMATION));
2790
2791 RtlCopyMemory(&BusInfo->BusTypeGuid,
2792 &GUID_BUS_TYPE_USB,
2793 sizeof(BusInfo->BusTypeGuid));
2794
2795 BusInfo->LegacyBusType = PNPBus;
2796 BusInfo->BusNumber = 0;
2797
2798 Irp->IoStatus.Information = (ULONG_PTR)BusInfo;
2799 Status = STATUS_SUCCESS;
2800 break;
2801
2802 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
2803 DPRINT_PNP("PDO IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
2804 DbgBreakPoint();
2805 Status = Irp->IoStatus.Status;
2806 break;
2807
2808 case IRP_MN_SURPRISE_REMOVAL:
2809 DPRINT_PNP("PDO IRP_MN_SURPRISE_REMOVAL\n");
2810 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REG_DEV_INTERFACE)
2811 {
2812 Status = USBH_SymbolicLink(PortExtension, NULL, FALSE);
2813
2814 if (NT_SUCCESS(Status))
2815 {
2816 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REG_DEV_INTERFACE;
2817 }
2818 }
2819
2820 Status = STATUS_SUCCESS;
2821 break;
2822
2823 default:
2824 DPRINT_PNP("PDO unknown IRP_MN_???\n");
2825 Status = Irp->IoStatus.Status;
2826 break;
2827 }
2828
2829 return Status;
2830 }