[NTFS]
[reactos.git] / drivers / usb / usbport / pnp.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort plug and play functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NDEBUG_USBPORT_CORE
14 #include "usbdebug.h"
15
16 IO_COMPLETION_ROUTINE USBPORT_FdoStartCompletion;
17
18 NTSTATUS
19 NTAPI
20 USBPORT_FdoStartCompletion(IN PDEVICE_OBJECT DeviceObject,
21 IN PIRP Irp,
22 IN PVOID Context)
23 {
24 KeSetEvent((PKEVENT)Context, EVENT_INCREMENT, FALSE);
25 return STATUS_MORE_PROCESSING_REQUIRED;
26 }
27
28 NTSTATUS
29 NTAPI
30 USBPORT_RegisterDeviceInterface(IN PDEVICE_OBJECT PdoDevice,
31 IN PDEVICE_OBJECT DeviceObject,
32 IN CONST GUID *InterfaceClassGuid,
33 IN BOOLEAN Enable)
34 {
35 PUSBPORT_RHDEVICE_EXTENSION DeviceExtension;
36 PUNICODE_STRING SymbolicLinkName;
37 NTSTATUS Status;
38
39 DPRINT("USBPORT_RegisterDeviceInterface: Enable - %x\n", Enable);
40
41 DeviceExtension = DeviceObject->DeviceExtension;
42 SymbolicLinkName = &DeviceExtension->CommonExtension.SymbolicLinkName;
43
44 if (Enable)
45 {
46 Status = IoRegisterDeviceInterface(PdoDevice,
47 InterfaceClassGuid,
48 NULL,
49 SymbolicLinkName);
50
51 if (NT_SUCCESS(Status))
52 {
53 DeviceExtension->CommonExtension.IsInterfaceEnabled = 1;
54
55 Status = USBPORT_SetRegistryKeyValue(PdoDevice,
56 FALSE,
57 REG_SZ,
58 L"SymbolicName",
59 SymbolicLinkName->Buffer,
60 SymbolicLinkName->Length);
61
62 if (NT_SUCCESS(Status))
63 {
64 DPRINT("USBPORT_RegisterDeviceInterface: LinkName - %wZ\n",
65 &DeviceExtension->CommonExtension.SymbolicLinkName);
66
67 Status = IoSetDeviceInterfaceState(SymbolicLinkName, TRUE);
68 }
69 }
70 }
71 else
72 {
73 /* Disable device interface */
74 Status = IoSetDeviceInterfaceState(SymbolicLinkName, FALSE);
75
76 if (NT_SUCCESS(Status))
77 {
78 RtlFreeUnicodeString(SymbolicLinkName);
79 DeviceExtension->CommonExtension.IsInterfaceEnabled = 0; // Disabled interface
80 }
81 }
82
83 return Status;
84 }
85
86 BOOLEAN
87 NTAPI
88 USBPORT_IsSelectiveSuspendEnabled(IN PDEVICE_OBJECT FdoDevice)
89 {
90 PUSBPORT_DEVICE_EXTENSION FdoExtension;
91 ULONG Disabled = 0;
92
93 DPRINT("USBPORT_IsSelectiveSuspendEnabled: ... \n");
94
95 FdoExtension = FdoDevice->DeviceExtension;
96
97 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
98 FdoExtension->CommonExtension.LowerPdoDevice,
99 TRUE,
100 L"HcDisableSelectiveSuspend",
101 sizeof(L"HcDisableSelectiveSuspend"),
102 &Disabled,
103 sizeof(Disabled));
104
105 return (Disabled == 0);
106 }
107
108 NTSTATUS
109 NTAPI
110 USBPORT_GetConfigValue(IN PWSTR ValueName,
111 IN ULONG ValueType,
112 IN PVOID ValueData,
113 IN ULONG ValueLength,
114 IN PVOID Context,
115 IN PVOID EntryContext)
116 {
117 NTSTATUS Status = STATUS_SUCCESS;
118
119 DPRINT("USBPORT_GetConfigValue \n");
120
121 if (ValueType == REG_DWORD)
122 {
123 *(PULONG)EntryContext = *(PULONG)ValueData;
124 }
125 else
126 {
127 Status = STATUS_INVALID_PARAMETER;
128 }
129
130 return Status;
131 }
132
133 NTSTATUS
134 NTAPI
135 USBPORT_GetDefaultBIOSx(IN PDEVICE_OBJECT FdoDevice,
136 IN PULONG UsbBIOSx,
137 IN PULONG DisableSelectiveSuspend,
138 IN PULONG DisableCcDetect,
139 IN PULONG IdleEpSupport,
140 IN PULONG IdleEpSupportEx,
141 IN PULONG SoftRetry)
142 {
143 RTL_QUERY_REGISTRY_TABLE QueryTable[7];
144
145 DPRINT("USBPORT_GetDefaultBIOS_X: ... \n");
146
147 RtlZeroMemory(QueryTable, sizeof(QueryTable));
148
149 *UsbBIOSx = 2;
150
151 QueryTable[0].QueryRoutine = USBPORT_GetConfigValue;
152 QueryTable[0].Flags = 0;
153 QueryTable[0].Name = L"UsbBIOSx";
154 QueryTable[0].EntryContext = UsbBIOSx;
155 QueryTable[0].DefaultType = REG_DWORD;
156 QueryTable[0].DefaultData = UsbBIOSx;
157 QueryTable[0].DefaultLength = sizeof(ULONG);
158
159 QueryTable[1].QueryRoutine = USBPORT_GetConfigValue;
160 QueryTable[1].Flags = 0;
161 QueryTable[1].Name = L"DisableSelectiveSuspend";
162 QueryTable[1].EntryContext = DisableSelectiveSuspend;
163 QueryTable[1].DefaultType = REG_DWORD;
164 QueryTable[1].DefaultData = DisableSelectiveSuspend;
165 QueryTable[1].DefaultLength = sizeof(ULONG);
166
167 QueryTable[2].QueryRoutine = USBPORT_GetConfigValue;
168 QueryTable[2].Flags = 0;
169 QueryTable[2].Name = L"DisableCcDetect";
170 QueryTable[2].EntryContext = DisableCcDetect;
171 QueryTable[2].DefaultType = REG_DWORD;
172 QueryTable[2].DefaultData = DisableCcDetect;
173 QueryTable[2].DefaultLength = sizeof(ULONG);
174
175 QueryTable[3].QueryRoutine = USBPORT_GetConfigValue;
176 QueryTable[3].Flags = 0;
177 QueryTable[3].Name = L"EnIdleEndpointSupport";
178 QueryTable[3].EntryContext = IdleEpSupport;
179 QueryTable[3].DefaultType = REG_DWORD;
180 QueryTable[3].DefaultData = IdleEpSupport;
181 QueryTable[3].DefaultLength = sizeof(ULONG);
182
183 QueryTable[4].QueryRoutine = USBPORT_GetConfigValue;
184 QueryTable[4].Flags = 0;
185 QueryTable[4].Name = L"EnIdleEndpointSupportEx";
186 QueryTable[4].EntryContext = IdleEpSupportEx;
187 QueryTable[4].DefaultType = REG_DWORD;
188 QueryTable[4].DefaultData = IdleEpSupportEx;
189 QueryTable[4].DefaultLength = sizeof(ULONG);
190
191 QueryTable[5].QueryRoutine = USBPORT_GetConfigValue;
192 QueryTable[5].Flags = 0;
193 QueryTable[5].Name = L"EnSoftRetry";
194 QueryTable[5].EntryContext = SoftRetry;
195 QueryTable[5].DefaultType = REG_DWORD;
196 QueryTable[5].DefaultData = SoftRetry;
197 QueryTable[5].DefaultLength = sizeof(ULONG);
198
199 return RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
200 L"usb",
201 QueryTable,
202 NULL,
203 NULL);
204 }
205
206 NTSTATUS
207 NTAPI
208 USBPORT_IsCompanionController(IN PDEVICE_OBJECT DeviceObject,
209 IN BOOLEAN *IsCompanion)
210 {
211 PDEVICE_OBJECT HighestDevice;
212 PIRP Irp;
213 KEVENT Event;
214 PIO_STACK_LOCATION IoStack;
215 PCI_DEVICE_PRESENT_INTERFACE PciInterface = {0};
216 PCI_DEVICE_PRESENCE_PARAMETERS Parameters = {0};
217 IO_STATUS_BLOCK IoStatusBlock;
218 NTSTATUS Status;
219 BOOLEAN IsPresent;
220
221 DPRINT("USBPORT_IsCompanionController: ... \n");
222
223 *IsCompanion = FALSE;
224
225 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
226
227 HighestDevice = IoGetAttachedDeviceReference(DeviceObject);
228
229 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
230 HighestDevice,
231 NULL,
232 0,
233 NULL,
234 &Event,
235 &IoStatusBlock);
236
237 if (!Irp)
238 {
239 Status = STATUS_INSUFFICIENT_RESOURCES;
240 ObDereferenceObject(HighestDevice);
241 return Status;
242 }
243
244 IoStack = IoGetNextIrpStackLocation(Irp);
245
246 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
247 Irp->IoStatus.Information = 0;
248
249 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
250
251 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE;
252 IoStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
253 IoStack->Parameters.QueryInterface.Version = 1;
254 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)&PciInterface;
255 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
256
257 Status = IoCallDriver(HighestDevice, Irp);
258
259 if (Status == STATUS_PENDING)
260 {
261 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
262 Status = IoStatusBlock.Status;
263 }
264
265 if (!NT_SUCCESS(Status))
266 {
267 DPRINT1("USBPORT_IsCompanionController: query interface failed\\n");
268 ObDereferenceObject(HighestDevice);
269 return Status;
270 }
271
272 DPRINT("USBPORT_IsCompanionController: query interface succeeded\n");
273
274 if (PciInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
275 {
276 DPRINT1("USBPORT_IsCompanionController: old version\n");
277 ObDereferenceObject(HighestDevice);
278 return Status;
279 }
280
281 Parameters.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
282
283 Parameters.BaseClass = PCI_CLASS_SERIAL_BUS_CTLR;
284 Parameters.SubClass = PCI_SUBCLASS_SB_USB;
285 Parameters.ProgIf = PCI_INTERFACE_USB_ID_EHCI;
286
287 Parameters.Flags = PCI_USE_LOCAL_BUS |
288 PCI_USE_LOCAL_DEVICE |
289 PCI_USE_CLASS_SUBCLASS |
290 PCI_USE_PROGIF;
291
292 IsPresent = (PciInterface.IsDevicePresentEx)(PciInterface.Context,
293 &Parameters);
294
295 if (IsPresent)
296 {
297 DPRINT("USBPORT_IsCompanionController: Present EHCI controller for FDO - %p\n",
298 DeviceObject);
299 }
300 else
301 {
302 DPRINT("USBPORT_IsCompanionController: No EHCI controller for FDO - %p\n",
303 DeviceObject);
304 }
305
306 *IsCompanion = IsPresent;
307
308 (PciInterface.InterfaceDereference)(PciInterface.Context);
309
310 ObDereferenceObject(HighestDevice);
311
312 return Status;
313 }
314
315 NTSTATUS
316 NTAPI
317 USBPORT_QueryPciBusInterface(IN PDEVICE_OBJECT FdoDevice)
318 {
319 PUSBPORT_DEVICE_EXTENSION FdoExtension;
320 PBUS_INTERFACE_STANDARD BusInterface;
321 PIO_STACK_LOCATION IoStack;
322 IO_STATUS_BLOCK IoStatusBlock;
323 PDEVICE_OBJECT HighestDevice;
324 KEVENT Event;
325 PIRP Irp;
326 NTSTATUS Status;
327
328 DPRINT("USBPORT_QueryPciBusInterface: ... \n");
329
330 FdoExtension = FdoDevice->DeviceExtension;
331 BusInterface = &FdoExtension->BusInterface;
332
333 RtlZeroMemory(BusInterface, sizeof(BUS_INTERFACE_STANDARD));
334 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
335 HighestDevice = IoGetAttachedDeviceReference(FdoDevice);
336
337 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
338 HighestDevice,
339 NULL,
340 0,
341 NULL,
342 &Event,
343 &IoStatusBlock);
344
345 if (Irp)
346 {
347 IoStack = IoGetNextIrpStackLocation(Irp);
348
349 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
350 Irp->IoStatus.Information = 0;
351
352 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
353
354 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
355 IoStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
356 IoStack->Parameters.QueryInterface.Version = 1;
357 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
358 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
359
360 Status = IoCallDriver(HighestDevice, Irp);
361
362 if (Status == STATUS_PENDING)
363 {
364 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
365 Status = IoStatusBlock.Status;
366 }
367 }
368 else
369 {
370 Status = STATUS_INSUFFICIENT_RESOURCES;
371 }
372
373 ObDereferenceObject(HighestDevice);
374
375 DPRINT("USBPORT_QueryPciBusInterface: return Status - %x\n", Status);
376
377 return Status;
378 }
379
380 NTSTATUS
381 NTAPI
382 USBPORT_QueryCapabilities(IN PDEVICE_OBJECT FdoDevice,
383 IN PDEVICE_CAPABILITIES Capabilities)
384 {
385 PUSBPORT_DEVICE_EXTENSION FdoExtention;
386 PIRP Irp;
387 NTSTATUS Status;
388 PIO_STACK_LOCATION IoStack;
389 KEVENT Event;
390
391 DPRINT("USBPORT_QueryCapabilities: ... \n");
392
393 FdoExtention = FdoDevice->DeviceExtension;
394
395 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
396
397 Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
398 Capabilities->Version = 1;
399 Capabilities->Address = MAXULONG;
400 Capabilities->UINumber = MAXULONG;
401
402 Irp = IoAllocateIrp(FdoExtention->CommonExtension.LowerDevice->StackSize,
403 FALSE);
404
405 if (!Irp)
406 {
407 DPRINT1("USBPORT_QueryCapabilities: No resources - IoAllocateIrp!\n");
408 return STATUS_INSUFFICIENT_RESOURCES;
409 }
410
411 IoStack = IoGetCurrentIrpStackLocation(Irp);
412 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
413
414 IoStack = IoGetNextIrpStackLocation(Irp);
415 IoStack->MajorFunction = IRP_MJ_PNP;
416 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
417
418 KeInitializeEvent(&Event, NotificationEvent, FALSE);
419
420 IoSetCompletionRoutine(Irp,
421 USBPORT_FdoStartCompletion,
422 &Event,
423 TRUE,
424 TRUE,
425 TRUE);
426
427 IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
428
429 Status = IoCallDriver(FdoExtention->CommonExtension.LowerDevice, Irp);
430
431 if (Status == STATUS_PENDING)
432 {
433 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
434 Status = Irp->IoStatus.Status;
435 }
436
437 if (NT_SUCCESS(Status) && Capabilities)
438 {
439 USBPORT_DumpingCapabilities(Capabilities);
440 }
441
442 IoFreeIrp(Irp);
443
444 return Status;
445 }
446
447 NTSTATUS
448 NTAPI
449 USBPORT_CreateLegacySymbolicLink(IN PDEVICE_OBJECT FdoDevice)
450 {
451 PUSBPORT_DEVICE_EXTENSION FdoExtension;
452 WCHAR CharName[255] = {0};
453 WCHAR CharDosName[255] = {0};
454 UNICODE_STRING DeviceName;
455 NTSTATUS Status;
456
457 FdoExtension = FdoDevice->DeviceExtension;
458
459 RtlStringCbPrintfW(CharName,
460 sizeof(CharName),
461 L"\\Device\\USBFDO-%d",
462 FdoExtension->FdoNameNumber);
463
464 RtlInitUnicodeString(&DeviceName, CharName);
465
466 RtlStringCbPrintfW(CharDosName,
467 sizeof(CharDosName),
468 L"\\DosDevices\\HCD%d",
469 FdoExtension->FdoNameNumber);
470
471 RtlInitUnicodeString(&FdoExtension->DosDeviceSymbolicName, CharDosName);
472
473 DPRINT("USBPORT_CreateLegacySymbolicLink: DeviceName - %wZ, DosSymbolicName - %wZ\n",
474 &DeviceName,
475 &FdoExtension->DosDeviceSymbolicName);
476
477 Status = IoCreateSymbolicLink(&FdoExtension->DosDeviceSymbolicName,
478 &DeviceName);
479
480 if (NT_SUCCESS(Status))
481 {
482 FdoExtension->Flags |= USBPORT_FLAG_DOS_SYMBOLIC_NAME;
483 }
484
485 return Status;
486 }
487
488 NTSTATUS
489 NTAPI
490 USBPORT_StopDevice(IN PDEVICE_OBJECT FdoDevice)
491 {
492 DPRINT1("USBPORT_StopDevice: UNIMPLEMENTED. FIXME\n");
493 DbgBreakPoint();
494 return STATUS_SUCCESS;
495 }
496
497 NTSTATUS
498 NTAPI
499 USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
500 IN PUSBPORT_RESOURCES UsbPortResources)
501 {
502 PUSBPORT_DEVICE_EXTENSION FdoExtension;
503 PUSBPORT_REGISTRATION_PACKET Packet;
504 NTSTATUS Status;
505 PCI_COMMON_CONFIG PciConfig;
506 ULONG BytesRead;
507 DEVICE_DESCRIPTION DeviceDescription;
508 PDMA_ADAPTER DmaAdapter = NULL;
509 ULONG MiniPortStatus;
510 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
511 ULONG ResultLength;
512 ULONG DisableSelectiveSuspend = 0;
513 ULONG DisableCcDetect = 0;
514 ULONG IdleEpSupport = 0;
515 ULONG IdleEpSupportEx = 0;
516 ULONG SoftRetry = 0;
517 ULONG Limit2GB = 0;
518 ULONG TotalBusBandwidth = 0;
519 BOOLEAN IsCompanion = FALSE;
520 ULONG LegacyBIOS;
521 ULONG MiniportFlags;
522
523 DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
524 FdoDevice,
525 UsbPortResources);
526
527 FdoExtension = FdoDevice->DeviceExtension;
528 Packet = &FdoExtension->MiniPortInterface->Packet;
529
530 Status = USBPORT_QueryPciBusInterface(FdoDevice);
531 if (!NT_SUCCESS(Status))
532 goto ExitWithError;
533
534 BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
535 PCI_WHICHSPACE_CONFIG,
536 &PciConfig,
537 0,
538 PCI_COMMON_HDR_LENGTH);
539
540 if (BytesRead != PCI_COMMON_HDR_LENGTH)
541 {
542 DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n");
543 goto ExitWithError;
544 }
545
546 FdoExtension->VendorID = PciConfig.VendorID;
547 FdoExtension->DeviceID = PciConfig.DeviceID;
548 FdoExtension->RevisionID = PciConfig.RevisionID;
549 FdoExtension->ProgIf = PciConfig.ProgIf;
550 FdoExtension->SubClass = PciConfig.SubClass;
551 FdoExtension->BaseClass = PciConfig.BaseClass;
552
553 RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
554
555 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
556 DeviceDescription.Master = TRUE;
557 DeviceDescription.ScatterGather = TRUE;
558 DeviceDescription.Dma32BitAddresses = TRUE;
559 DeviceDescription.InterfaceType = PCIBus;
560 DeviceDescription.DmaWidth = Width32Bits;
561 DeviceDescription.DmaSpeed = Compatible;
562 DeviceDescription.MaximumLength = MAXULONG;
563
564 DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice,
565 &DeviceDescription,
566 &FdoExtension->NumberMapRegs);
567
568 FdoExtension->DmaAdapter = DmaAdapter;
569
570 if (!DmaAdapter)
571 {
572 DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n");
573 Status = STATUS_INSUFFICIENT_RESOURCES;
574 goto ExitWithError;
575 }
576
577 Status = USBPORT_CreateWorkerThread(FdoDevice);
578 if (!NT_SUCCESS(Status))
579 goto ExitWithError;
580
581 Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities);
582 if (!NT_SUCCESS(Status))
583 goto ExitWithError;
584
585 FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16;
586 FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF;
587
588 Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
589 DevicePropertyBusNumber,
590 sizeof(ULONG),
591 &FdoExtension->BusNumber,
592 &ResultLength);
593
594 if (!NT_SUCCESS(Status))
595 goto ExitWithError;
596
597 KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock);
598 KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock);
599 KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock);
600 KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock);
601 KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock);
602 KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock);
603 KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock);
604 KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock);
605 KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock);
606 KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock);
607 KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock);
608 KeInitializeSpinLock(&FdoExtension->MiniportSpinLock);
609 KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock);
610 KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
611 KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
612 KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
613
614 KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
615
616 KeInitializeDpc(&FdoExtension->TransferFlushDpc,
617 USBPORT_TransferFlushDpc,
618 FdoDevice);
619
620 KeInitializeDpc(&FdoExtension->WorkerRequestDpc,
621 USBPORT_WorkerRequestDpc,
622 FdoDevice);
623
624 KeInitializeDpc(&FdoExtension->HcWakeDpc,
625 USBPORT_HcWakeDpc,
626 FdoDevice);
627
628 IoCsqInitialize(&FdoExtension->IdleIoCsq,
629 USBPORT_InsertIdleIrp,
630 USBPORT_RemoveIdleIrp,
631 USBPORT_PeekNextIdleIrp,
632 USBPORT_AcquireIdleLock,
633 USBPORT_ReleaseIdleLock,
634 USBPORT_CompleteCanceledIdleIrp);
635
636 IoCsqInitialize(&FdoExtension->BadRequestIoCsq,
637 USBPORT_InsertBadRequest,
638 USBPORT_RemoveBadRequest,
639 USBPORT_PeekNextBadRequest,
640 USBPORT_AcquireBadRequestLock,
641 USBPORT_ReleaseBadRequestLock,
642 USBPORT_CompleteCanceledBadRequest);
643
644 FdoExtension->IsrDpcCounter = -1;
645 FdoExtension->IsrDpcHandlerCounter = -1;
646 FdoExtension->IdleLockCounter = -1;
647 FdoExtension->BadRequestLockCounter = -1;
648 FdoExtension->ChirpRootPortLock = -1;
649
650 FdoExtension->RHInitCallBackLock = 0;
651
652 FdoExtension->UsbAddressBitMap[0] = 1;
653 FdoExtension->UsbAddressBitMap[1] = 0;
654 FdoExtension->UsbAddressBitMap[2] = 0;
655 FdoExtension->UsbAddressBitMap[3] = 0;
656
657 USBPORT_GetDefaultBIOSx(FdoDevice,
658 &FdoExtension->UsbBIOSx,
659 &DisableSelectiveSuspend,
660 &DisableCcDetect,
661 &IdleEpSupport,
662 &IdleEpSupportEx,
663 &SoftRetry);
664
665 if (DisableSelectiveSuspend)
666 FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS;
667
668 if (!DisableSelectiveSuspend &&
669 USBPORT_IsSelectiveSuspendEnabled(FdoDevice))
670 {
671 FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
672 }
673
674 MiniportFlags = Packet->MiniPortFlags;
675
676 if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING)
677 FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING;
678
679 if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT)
680 FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT;
681
682 if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS)
683 FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) |
684 USBPORT_FLAG_BIOS_DISABLE_SS;
685
686 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
687 TRUE,
688 REG_DWORD,
689 L"EnIdleEndpointSupport",
690 &IdleEpSupport,
691 sizeof(IdleEpSupport));
692
693 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
694 TRUE,
695 REG_DWORD,
696 L"EnIdleEndpointSupportEx",
697 &IdleEpSupportEx,
698 sizeof(IdleEpSupportEx));
699
700 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
701 TRUE,
702 REG_DWORD,
703 L"EnSoftRetry",
704 &SoftRetry,
705 sizeof(SoftRetry));
706
707 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
708 FdoExtension->CommonExtension.LowerPdoDevice,
709 TRUE,
710 L"CommonBuffer2GBLimit",
711 sizeof(L"CommonBuffer2GBLimit"),
712 &Limit2GB,
713 sizeof(Limit2GB));
714
715 FdoExtension->CommonBufferLimit = (Limit2GB != 0);
716
717 if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR &&
718 FdoExtension->SubClass == PCI_SUBCLASS_SB_USB &&
719 FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI)
720 {
721 Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion);
722
723 if (!NT_SUCCESS(Status))
724 {
725 if (IsCompanion)
726 {
727 FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC;
728 }
729 else
730 {
731 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
732 }
733 }
734 }
735
736 if (DisableCcDetect)
737 {
738 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
739 }
740
741 TotalBusBandwidth = Packet->MiniPortBusBandwidth;
742 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
743
744 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
745 FdoExtension->CommonExtension.LowerPdoDevice,
746 TRUE,
747 L"TotalBusBandwidth",
748 sizeof(L"TotalBusBandwidth"),
749 &TotalBusBandwidth,
750 sizeof(TotalBusBandwidth));
751
752 if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth)
753 {
754 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
755 }
756
757 FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
758 sizeof(USBPORT_IRP_TABLE),
759 USB_PORT_TAG);
760
761 if (!FdoExtension->ActiveIrpTable)
762 {
763 DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n");
764 goto ExitWithError;
765 }
766
767 RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE));
768
769 FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool,
770 sizeof(USBPORT_IRP_TABLE),
771 USB_PORT_TAG);
772
773 if (!FdoExtension->PendingIrpTable)
774 {
775 DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n");
776 goto ExitWithError;
777 }
778
779 RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE));
780
781 Status = IoConnectInterrupt(&FdoExtension->InterruptObject,
782 USBPORT_InterruptService,
783 (PVOID)FdoDevice,
784 0,
785 UsbPortResources->InterruptVector,
786 UsbPortResources->InterruptLevel,
787 UsbPortResources->InterruptLevel,
788 UsbPortResources->InterruptMode,
789 UsbPortResources->ShareVector,
790 UsbPortResources->InterruptAffinity,
791 0);
792
793
794 if (!NT_SUCCESS(Status))
795 {
796 DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n");
797 goto ExitWithError;
798 }
799
800 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
801
802 if (Packet->MiniPortExtensionSize)
803 {
804 RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
805 }
806
807 if (Packet->MiniPortResourcesSize)
808 {
809 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
810 Packet->MiniPortResourcesSize);
811
812 if (!HeaderBuffer)
813 {
814 DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n");
815 Status = STATUS_INSUFFICIENT_RESOURCES;
816 goto ExitWithError;
817 }
818
819 UsbPortResources->StartVA = (PVOID)HeaderBuffer->VirtualAddress;
820 UsbPortResources->StartPA = (PVOID)HeaderBuffer->PhysicalAddress;
821
822 FdoExtension->MiniPortCommonBuffer = HeaderBuffer;
823 }
824 else
825 {
826 FdoExtension->MiniPortCommonBuffer = NULL;
827 }
828
829 MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt,
830 UsbPortResources);
831
832 if (UsbPortResources->LegacySupport)
833 {
834 FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT;
835 LegacyBIOS = 1;
836 }
837 else
838 {
839 LegacyBIOS = 0;
840 }
841
842 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
843 FALSE,
844 REG_DWORD,
845 L"DetectedLegacyBIOS",
846 &LegacyBIOS,
847 sizeof(LegacyBIOS));
848
849 if (MiniPortStatus)
850 {
851 DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n",
852 MiniPortStatus);
853
854 if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED)
855 {
856 IoDisconnectInterrupt(FdoExtension->InterruptObject);
857 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
858 }
859
860 if (FdoExtension->MiniPortCommonBuffer)
861 {
862 USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer);
863 FdoExtension->MiniPortCommonBuffer = NULL;
864 }
865
866 goto ExitWithError;
867 }
868 else
869 {
870 FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED;
871 USBPORT_MiniportInterrupts(FdoDevice, TRUE);
872 }
873
874 FdoExtension->TimerValue = 500;
875 USBPORT_StartTimer((PVOID)FdoDevice, 500);
876
877 Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice,
878 FdoDevice,
879 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
880 TRUE);
881
882 if (!NT_SUCCESS(Status))
883 {
884 DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n");
885 goto ExitWithError;
886 }
887
888 USBPORT_CreateLegacySymbolicLink(FdoDevice);
889
890 FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED;
891
892 DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status);
893 return Status;
894
895 ExitWithError:
896 USBPORT_StopDevice(FdoDevice);
897
898 DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status);
899 return Status;
900 }
901
902 NTSTATUS
903 NTAPI
904 USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice,
905 IN PIRP Irp,
906 IN PUSBPORT_RESOURCES UsbPortResources)
907 {
908 PCM_RESOURCE_LIST AllocatedResourcesTranslated;
909 PCM_PARTIAL_RESOURCE_LIST ResourceList;
910 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
911 PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL;
912 PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL;
913 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
914 PIO_STACK_LOCATION IoStack;
915 ULONG ix;
916 NTSTATUS Status = STATUS_SUCCESS;
917
918 DPRINT("USBPORT_ParseResources: ... \n");
919
920 IoStack = IoGetCurrentIrpStackLocation(Irp);
921 AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
922
923 if (AllocatedResourcesTranslated)
924 {
925 RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES));
926
927 ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList;
928
929 PartialDescriptor = &ResourceList->PartialDescriptors[0];
930
931 for (ix = 0; ix < ResourceList->Count; ++ix)
932 {
933 if (PartialDescriptor->Type == CmResourceTypePort)
934 {
935 if (!PortDescriptor)
936 PortDescriptor = PartialDescriptor;
937 }
938 else if (PartialDescriptor->Type == CmResourceTypeInterrupt)
939 {
940 if (!InterruptDescriptor)
941 InterruptDescriptor = PartialDescriptor;
942 }
943 else if (PartialDescriptor->Type == CmResourceTypeMemory)
944 {
945 if (!MemoryDescriptor)
946 MemoryDescriptor = PartialDescriptor;
947 }
948
949 PartialDescriptor += 1;
950 }
951
952 if (PortDescriptor)
953 {
954 if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO)
955 {
956 UsbPortResources->ResourceBase = (PVOID)PortDescriptor->u.Port.Start.LowPart;
957 }
958 else
959 {
960 UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start,
961 PortDescriptor->u.Port.Length,
962 0);
963 }
964
965 UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length;
966
967 if (UsbPortResources->ResourceBase)
968 {
969 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT;
970 }
971 else
972 {
973 Status = STATUS_NONE_MAPPED;
974 }
975 }
976
977 if (MemoryDescriptor && NT_SUCCESS(Status))
978 {
979 UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length;
980
981 UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start,
982 MemoryDescriptor->u.Memory.Length,
983 0);
984
985 if (UsbPortResources->ResourceBase)
986 {
987 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY;
988 }
989 else
990 {
991 Status = STATUS_NONE_MAPPED;
992 }
993 }
994
995 if (InterruptDescriptor && NT_SUCCESS(Status))
996 {
997 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT;
998
999 UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
1000 UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
1001 UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
1002
1003 UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition ==
1004 CmResourceShareShared;
1005
1006 UsbPortResources->InterruptMode = InterruptDescriptor->Flags ==
1007 CM_RESOURCE_INTERRUPT_LATCHED;
1008 }
1009 }
1010 else
1011 {
1012 Status = STATUS_NONE_MAPPED;
1013 }
1014
1015 return Status;
1016 }
1017
1018 NTSTATUS
1019 NTAPI
1020 USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice,
1021 OUT PDEVICE_OBJECT *RootHubPdo)
1022 {
1023 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1024 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1025 UNICODE_STRING DeviceName;
1026 ULONG DeviceNumber = 0;
1027 PDEVICE_OBJECT DeviceObject = NULL;
1028 WCHAR CharDeviceName[64];
1029 NTSTATUS Status = STATUS_SUCCESS;
1030
1031 DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n",
1032 FdoDevice,
1033 RootHubPdo);
1034
1035 FdoExtension = FdoDevice->DeviceExtension;
1036
1037 do
1038 {
1039 RtlStringCbPrintfW(CharDeviceName,
1040 sizeof(CharDeviceName),
1041 L"\\Device\\USBPDO-%d",
1042 DeviceNumber);
1043
1044 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1045
1046 DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName);
1047
1048 Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject,
1049 sizeof(USBPORT_RHDEVICE_EXTENSION),
1050 &DeviceName,
1051 FILE_DEVICE_BUS_EXTENDER,
1052 0,
1053 FALSE,
1054 &DeviceObject);
1055
1056 ++DeviceNumber;
1057 }
1058 while (Status == STATUS_OBJECT_NAME_COLLISION);
1059
1060 if (!NT_SUCCESS(Status))
1061 {
1062 *RootHubPdo = NULL;
1063 DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n");
1064 return Status;
1065 }
1066
1067 if (DeviceObject)
1068 {
1069 PdoExtension = DeviceObject->DeviceExtension;
1070
1071 RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION));
1072
1073 PdoExtension->CommonExtension.SelfDevice = DeviceObject;
1074 PdoExtension->CommonExtension.IsPDO = TRUE;
1075
1076 PdoExtension->FdoDevice = FdoDevice;
1077 PdoExtension->PdoNameNumber = DeviceNumber;
1078
1079 USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject);
1080
1081 DeviceObject->StackSize = FdoDevice->StackSize;
1082
1083 DeviceObject->Flags |= DO_POWER_PAGABLE;
1084 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1085 }
1086 else
1087 {
1088 Status = STATUS_UNSUCCESSFUL;
1089 }
1090
1091 if (!NT_SUCCESS(Status))
1092 *RootHubPdo = NULL;
1093 else
1094 *RootHubPdo = DeviceObject;
1095
1096 DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject);
1097 return Status;
1098 }
1099
1100 NTSTATUS
1101 NTAPI
1102 USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice,
1103 IN PIRP Irp)
1104 {
1105 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1106 PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1107 PUSBPORT_REGISTRATION_PACKET Packet;
1108 PUSBPORT_RESOURCES UsbPortResources;
1109 PIO_STACK_LOCATION IoStack;
1110 UCHAR Minor;
1111 KEVENT Event;
1112 NTSTATUS Status;
1113 DEVICE_RELATION_TYPE RelationType;
1114 PDEVICE_RELATIONS DeviceRelations;
1115 PDEVICE_OBJECT RootHubPdo;
1116
1117 FdoExtension = FdoDevice->DeviceExtension;
1118 FdoCommonExtension = &FdoExtension->CommonExtension;
1119 UsbPortResources = &FdoExtension->UsbPortResources;
1120 Packet = &FdoExtension->MiniPortInterface->Packet;
1121
1122 IoStack = IoGetCurrentIrpStackLocation(Irp);
1123 Minor = IoStack->MinorFunction;
1124
1125 DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor);
1126
1127 RelationType = IoStack->Parameters.QueryDeviceRelations.Type;
1128
1129 switch (Minor)
1130 {
1131 case IRP_MN_START_DEVICE:
1132 DPRINT("IRP_MN_START_DEVICE\n");
1133
1134 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1135
1136 IoCopyCurrentIrpStackLocationToNext(Irp);
1137
1138 IoSetCompletionRoutine(Irp,
1139 USBPORT_FdoStartCompletion,
1140 &Event,
1141 TRUE,
1142 TRUE,
1143 TRUE);
1144
1145 Status = IoCallDriver(FdoCommonExtension->LowerDevice,
1146 Irp);
1147
1148 if (Status == STATUS_PENDING)
1149 {
1150 KeWaitForSingleObject(&Event,
1151 Suspended,
1152 KernelMode,
1153 FALSE,
1154 NULL);
1155
1156 Status = Irp->IoStatus.Status;
1157 }
1158
1159 if (!NT_SUCCESS(Status))
1160 {
1161 goto Exit;
1162 }
1163
1164 Status = USBPORT_ParseResources(FdoDevice,
1165 Irp,
1166 UsbPortResources);
1167
1168 if (!NT_SUCCESS(Status))
1169 {
1170 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1171 goto Exit;
1172 }
1173
1174 Status = USBPORT_StartDevice(FdoDevice, UsbPortResources);
1175
1176 if (!NT_SUCCESS(Status))
1177 {
1178 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1179 goto Exit;
1180 }
1181
1182 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT;
1183 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED;
1184
1185 FdoCommonExtension->DevicePowerState = PowerDeviceD0;
1186
1187 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1188 {
1189 USBPORT_AddUSB2Fdo(FdoDevice);
1190 }
1191 else
1192 {
1193 USBPORT_AddUSB1Fdo(FdoDevice);
1194 }
1195
1196 Exit:
1197 Irp->IoStatus.Status = Status;
1198 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1199 return Status;
1200
1201 case IRP_MN_QUERY_REMOVE_DEVICE:
1202 DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
1203 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1204 {
1205 DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n");
1206 }
1207
1208 Irp->IoStatus.Status = STATUS_SUCCESS;
1209 goto ForwardIrp;
1210
1211 case IRP_MN_REMOVE_DEVICE:
1212 DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n");
1213 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED;
1214
1215 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED &&
1216 !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT))
1217 {
1218 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1219 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1220 }
1221
1222 Irp->IoStatus.Status = STATUS_SUCCESS;
1223 IoSkipCurrentIrpStackLocation(Irp);
1224 Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1225
1226 IoDetachDevice(FdoCommonExtension->LowerDevice);
1227
1228 RootHubPdo = FdoExtension->RootHubPdo;
1229
1230 IoDeleteDevice(FdoDevice);
1231
1232 if (RootHubPdo)
1233 {
1234 IoDeleteDevice(RootHubPdo);
1235 }
1236
1237 return Status;
1238
1239 case IRP_MN_CANCEL_REMOVE_DEVICE:
1240 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1241 Irp->IoStatus.Status = STATUS_SUCCESS;
1242 goto ForwardIrp;
1243
1244 case IRP_MN_STOP_DEVICE:
1245 DPRINT("IRP_MN_STOP_DEVICE\n");
1246 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED)
1247 {
1248 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1249
1250 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED;
1251 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1252 }
1253
1254 Irp->IoStatus.Status = STATUS_SUCCESS;
1255 goto ForwardIrp;
1256
1257 case IRP_MN_QUERY_STOP_DEVICE:
1258 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1259 Irp->IoStatus.Status = STATUS_SUCCESS;
1260 goto ForwardIrp;
1261
1262 case IRP_MN_CANCEL_STOP_DEVICE:
1263 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1264 Irp->IoStatus.Status = STATUS_SUCCESS;
1265 goto ForwardIrp;
1266
1267 case IRP_MN_QUERY_DEVICE_RELATIONS:
1268 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1269 if (RelationType == BusRelations)
1270 {
1271 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1272 sizeof(DEVICE_RELATIONS),
1273 USB_PORT_TAG);
1274
1275 if (!DeviceRelations)
1276 {
1277 Status = STATUS_INSUFFICIENT_RESOURCES;
1278 Irp->IoStatus.Status = Status;
1279 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1280 return Status;
1281 }
1282
1283 DeviceRelations->Count = 0;
1284 DeviceRelations->Objects[0] = NULL;
1285
1286 if (!FdoExtension->RootHubPdo)
1287 {
1288 Status = USBPORT_CreatePdo(FdoDevice,
1289 &FdoExtension->RootHubPdo);
1290
1291 if (!NT_SUCCESS(Status))
1292 {
1293 ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG);
1294 goto ForwardIrp;
1295 }
1296 }
1297 else
1298 {
1299 Status = STATUS_SUCCESS;
1300 }
1301
1302 DeviceRelations->Count = 1;
1303 DeviceRelations->Objects[0] = FdoExtension->RootHubPdo;
1304
1305 ObReferenceObject(FdoExtension->RootHubPdo);
1306 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1307 }
1308 else
1309 {
1310 if (RelationType == RemovalRelations)
1311 {
1312 DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n");
1313 }
1314
1315 goto ForwardIrp;
1316 }
1317
1318 Irp->IoStatus.Status = Status;
1319 goto ForwardIrp;
1320
1321 case IRP_MN_QUERY_INTERFACE:
1322 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1323 goto ForwardIrp;
1324
1325 case IRP_MN_QUERY_CAPABILITIES:
1326 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1327 goto ForwardIrp;
1328
1329 case IRP_MN_QUERY_RESOURCES:
1330 DPRINT("IRP_MN_QUERY_RESOURCES\n");
1331 goto ForwardIrp;
1332
1333 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1334 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1335 goto ForwardIrp;
1336
1337 case IRP_MN_QUERY_DEVICE_TEXT:
1338 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1339 goto ForwardIrp;
1340
1341 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1342 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1343 goto ForwardIrp;
1344
1345 case IRP_MN_READ_CONFIG:
1346 DPRINT("IRP_MN_READ_CONFIG\n");
1347 goto ForwardIrp;
1348
1349 case IRP_MN_WRITE_CONFIG:
1350 DPRINT("IRP_MN_WRITE_CONFIG\n");
1351 goto ForwardIrp;
1352
1353 case IRP_MN_EJECT:
1354 DPRINT("IRP_MN_EJECT\n");
1355 goto ForwardIrp;
1356
1357 case IRP_MN_SET_LOCK:
1358 DPRINT("IRP_MN_SET_LOCK\n");
1359 goto ForwardIrp;
1360
1361 case IRP_MN_QUERY_ID:
1362 DPRINT("IRP_MN_QUERY_ID\n");
1363 goto ForwardIrp;
1364
1365 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1366 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1367 goto ForwardIrp;
1368
1369 case IRP_MN_QUERY_BUS_INFORMATION:
1370 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1371 goto ForwardIrp;
1372
1373 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1374 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1375 goto ForwardIrp;
1376
1377 case IRP_MN_SURPRISE_REMOVAL:
1378 DPRINT1("IRP_MN_SURPRISE_REMOVAL\n");
1379 if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED))
1380 {
1381 USBPORT_InvalidateControllerHandler(FdoDevice,
1382 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
1383 }
1384 goto ForwardIrp;
1385
1386 default:
1387 DPRINT("unknown IRP_MN_???\n");
1388 ForwardIrp:
1389 /* forward irp to next device object */
1390 IoSkipCurrentIrpStackLocation(Irp);
1391 break;
1392 }
1393
1394 return IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1395 }
1396
1397 PVOID
1398 NTAPI
1399 USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice,
1400 IN USHORT VendorID,
1401 IN USHORT DeviceID,
1402 IN USHORT RevisionID)
1403 {
1404 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1405 PUSBPORT_REGISTRATION_PACKET Packet;
1406 PVOID Id;
1407 WCHAR Buffer[300] = {0};
1408 ULONG Length = 0;
1409 size_t Remaining = sizeof(Buffer);
1410 PWCHAR EndBuffer;
1411
1412 FdoExtension = FdoDevice->DeviceExtension;
1413 Packet = &FdoExtension->MiniPortInterface->Packet;
1414
1415 DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n",
1416 FdoDevice,
1417 Packet->MiniPortFlags);
1418
1419 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1420 {
1421 RtlStringCbPrintfExW(Buffer,
1422 Remaining,
1423 &EndBuffer,
1424 &Remaining,
1425 0,
1426 L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x",
1427 VendorID,
1428 DeviceID,
1429 RevisionID);
1430
1431 EndBuffer++;
1432 Remaining -= sizeof(UNICODE_NULL);
1433
1434 RtlStringCbPrintfExW(EndBuffer,
1435 Remaining,
1436 &EndBuffer,
1437 &Remaining,
1438 0,
1439 L"USB\\ROOT_HUB20&VID%04x&PID%04x",
1440 VendorID,
1441 DeviceID);
1442
1443 EndBuffer++;
1444 Remaining -= sizeof(UNICODE_NULL);
1445
1446 RtlStringCbPrintfExW(EndBuffer,
1447 Remaining,
1448 NULL,
1449 &Remaining,
1450 0,
1451 L"USB\\ROOT_HUB20");
1452 }
1453 else
1454 {
1455 RtlStringCbPrintfExW(Buffer,
1456 Remaining,
1457 &EndBuffer,
1458 &Remaining,
1459 0,
1460 L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x",
1461 VendorID,
1462 DeviceID,
1463 RevisionID);
1464
1465 EndBuffer++;
1466 Remaining -= sizeof(UNICODE_NULL);
1467
1468 RtlStringCbPrintfExW(EndBuffer,
1469 Remaining,
1470 &EndBuffer,
1471 &Remaining,
1472 0,
1473 L"USB\\ROOT_HUB&VID%04x&PID%04x",
1474 VendorID,
1475 DeviceID);
1476
1477 EndBuffer++;
1478 Remaining -= sizeof(UNICODE_NULL);
1479
1480 RtlStringCbPrintfExW(EndBuffer,
1481 Remaining,
1482 NULL,
1483 &Remaining,
1484 0,
1485 L"USB\\ROOT_HUB");
1486 }
1487
1488 Length = (sizeof(Buffer) - Remaining + sizeof(UNICODE_NULL));
1489
1490 /* for debug only */
1491 if (FALSE)
1492 {
1493 DPRINT("Hardware IDs:\n");
1494 USBPORT_DumpingIDs(Buffer);
1495 }
1496
1497 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG);
1498
1499 if (!Id)
1500 return NULL;
1501
1502 RtlMoveMemory(Id, Buffer, Length);
1503
1504 return Id;
1505 }
1506
1507 NTSTATUS
1508 NTAPI
1509 USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice,
1510 IN PIRP Irp)
1511 {
1512 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1513 PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension;
1514 PDEVICE_OBJECT FdoDevice;
1515 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1516 PIO_STACK_LOCATION IoStack;
1517 UCHAR Minor;
1518 NTSTATUS Status;
1519 PPNP_BUS_INFORMATION BusInformation;
1520 PDEVICE_CAPABILITIES DeviceCapabilities;
1521
1522 PdoExtension = PdoDevice->DeviceExtension;
1523 PdoCommonExtension = &PdoExtension->CommonExtension;
1524
1525 FdoDevice = PdoExtension->FdoDevice;
1526 FdoExtension = FdoDevice->DeviceExtension;
1527
1528 IoStack = IoGetCurrentIrpStackLocation(Irp);
1529 Minor = IoStack->MinorFunction;
1530
1531 Status = Irp->IoStatus.Status;
1532
1533 DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor);
1534
1535 switch (Minor)
1536 {
1537 case IRP_MN_START_DEVICE:
1538 DPRINT("IRP_MN_START_DEVICE\n");
1539
1540 Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice);
1541
1542 if (NT_SUCCESS(Status))
1543 {
1544 Status = USBPORT_RegisterDeviceInterface(PdoDevice,
1545 PdoDevice,
1546 &GUID_DEVINTERFACE_USB_HUB,
1547 TRUE);
1548
1549 if (NT_SUCCESS(Status))
1550 {
1551 PdoCommonExtension->DevicePowerState = PowerDeviceD0;
1552 PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED;
1553 }
1554 }
1555
1556 break;
1557
1558 case IRP_MN_QUERY_REMOVE_DEVICE:
1559 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n");
1560 Status = STATUS_SUCCESS;
1561 break;
1562
1563 case IRP_MN_REMOVE_DEVICE:
1564 DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n");
1565 //USBPORT_StopRootHub();
1566 Status = STATUS_SUCCESS;
1567 break;
1568
1569 case IRP_MN_CANCEL_REMOVE_DEVICE:
1570 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1571 Status = STATUS_SUCCESS;
1572 break;
1573
1574 case IRP_MN_STOP_DEVICE:
1575 DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n");
1576 //USBPORT_StopRootHub();
1577 Status = STATUS_SUCCESS;
1578 break;
1579
1580 case IRP_MN_QUERY_STOP_DEVICE:
1581 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1582 Status = STATUS_SUCCESS;
1583 break;
1584
1585 case IRP_MN_CANCEL_STOP_DEVICE:
1586 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1587 Status = STATUS_SUCCESS;
1588 break;
1589
1590 case IRP_MN_QUERY_DEVICE_RELATIONS:
1591 {
1592 PDEVICE_RELATIONS DeviceRelations;
1593
1594 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1595 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1596 {
1597 break;
1598 }
1599
1600 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1601 sizeof(DEVICE_RELATIONS),
1602 USB_PORT_TAG);
1603
1604 if (!DeviceRelations)
1605 {
1606 Status = STATUS_INSUFFICIENT_RESOURCES;
1607 Irp->IoStatus.Information = 0;
1608 break;
1609 }
1610
1611 DeviceRelations->Count = 1;
1612 DeviceRelations->Objects[0] = PdoDevice;
1613
1614 ObReferenceObject(PdoDevice);
1615
1616 Status = STATUS_SUCCESS;
1617 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1618 break;
1619 }
1620
1621 case IRP_MN_QUERY_INTERFACE:
1622 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1623 Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp);
1624 break;
1625
1626 case IRP_MN_QUERY_CAPABILITIES:
1627 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1628
1629 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
1630
1631 RtlCopyMemory(DeviceCapabilities,
1632 &PdoExtension->Capabilities,
1633 sizeof(DEVICE_CAPABILITIES));
1634
1635 Status = STATUS_SUCCESS;
1636 break;
1637
1638 case IRP_MN_QUERY_RESOURCES:
1639 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n");
1640 break;
1641
1642 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1643 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1644 break;
1645
1646 case IRP_MN_QUERY_DEVICE_TEXT:
1647 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1648 break;
1649
1650 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1651 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1652 break;
1653
1654 case IRP_MN_READ_CONFIG:
1655 DPRINT("IRP_MN_READ_CONFIG\n");
1656 ASSERT(FALSE);
1657 break;
1658
1659 case IRP_MN_WRITE_CONFIG:
1660 DPRINT("IRP_MN_WRITE_CONFIG\n");
1661 ASSERT(FALSE);
1662 break;
1663
1664 case IRP_MN_EJECT:
1665 DPRINT("IRP_MN_EJECT\n");
1666 ASSERT(FALSE);
1667 break;
1668
1669 case IRP_MN_SET_LOCK:
1670 DPRINT("IRP_MN_SET_LOCK\n");
1671 ASSERT(FALSE);
1672 break;
1673
1674 case IRP_MN_QUERY_ID:
1675 {
1676 ULONG IdType;
1677 LONG Length;
1678 WCHAR Buffer[64] = {0};
1679 PVOID Id;
1680
1681 Status = STATUS_SUCCESS;
1682 IdType = IoStack->Parameters.QueryId.IdType;
1683
1684 DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType);
1685
1686 if (IdType == BusQueryDeviceID)
1687 {
1688 PUSBPORT_REGISTRATION_PACKET Packet;
1689 Packet = &FdoExtension->MiniPortInterface->Packet;
1690
1691 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1692 {
1693 RtlStringCbPrintfW(Buffer,
1694 sizeof(Buffer),
1695 L"USB\\ROOT_HUB20");
1696 }
1697 else
1698 {
1699 RtlStringCbPrintfW(Buffer,
1700 sizeof(Buffer),
1701 L"USB\\ROOT_HUB");
1702 }
1703
1704 Length = (wcslen(Buffer) + 1);
1705
1706 Id = ExAllocatePoolWithTag(PagedPool,
1707 Length * sizeof(WCHAR),
1708 USB_PORT_TAG);
1709
1710 if (Id)
1711 {
1712 RtlZeroMemory(Id, Length * sizeof(WCHAR));
1713 RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer);
1714
1715 DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n",
1716 Id,
1717 Length);
1718 }
1719
1720 Irp->IoStatus.Information = (ULONG_PTR)Id;
1721 break;
1722 }
1723
1724 if (IdType == BusQueryHardwareIDs)
1725 {
1726 Id = USBPORT_GetDeviceHwIds(FdoDevice,
1727 FdoExtension->VendorID,
1728 FdoExtension->DeviceID,
1729 FdoExtension->RevisionID);
1730
1731 Irp->IoStatus.Information = (ULONG_PTR)Id;
1732 break;
1733 }
1734
1735 if (IdType == BusQueryCompatibleIDs ||
1736 IdType == BusQueryInstanceID)
1737 {
1738 Irp->IoStatus.Information = 0;
1739 break;
1740 }
1741
1742 /* IdType == BusQueryDeviceSerialNumber */
1743 Status = Irp->IoStatus.Status;
1744 break;
1745 }
1746
1747 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1748 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1749 Status = STATUS_SUCCESS;
1750 break;
1751
1752 case IRP_MN_QUERY_BUS_INFORMATION:
1753 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1754
1755 /* Allocate buffer for bus information */
1756 BusInformation = ExAllocatePoolWithTag(PagedPool,
1757 sizeof(PNP_BUS_INFORMATION),
1758 USB_PORT_TAG);
1759
1760 if (!BusInformation)
1761 {
1762 /* No memory */
1763 Status = STATUS_INSUFFICIENT_RESOURCES;
1764 break;
1765 }
1766
1767 RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION));
1768
1769 /* Copy BUS GUID */
1770 RtlMoveMemory(&BusInformation->BusTypeGuid,
1771 &GUID_BUS_TYPE_USB,
1772 sizeof(GUID));
1773
1774 /* Set bus type */
1775 BusInformation->LegacyBusType = PNPBus;
1776 BusInformation->BusNumber = 0;
1777
1778 Status = STATUS_SUCCESS;
1779 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
1780 break;
1781
1782 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1783 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1784 break;
1785
1786 case IRP_MN_SURPRISE_REMOVAL:
1787 DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n");
1788 Status = STATUS_SUCCESS;
1789 break;
1790
1791 default:
1792 DPRINT("unknown IRP_MN_???\n");
1793 break;
1794 }
1795
1796 Irp->IoStatus.Status = Status;
1797 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1798 return Status;
1799 }