[BLUE] Perform size/rectangle boundary checks on read/write operations. CORE-15108
[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 ULONG ix;
523
524 DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
525 FdoDevice,
526 UsbPortResources);
527
528 FdoExtension = FdoDevice->DeviceExtension;
529 Packet = &FdoExtension->MiniPortInterface->Packet;
530
531 Status = USBPORT_QueryPciBusInterface(FdoDevice);
532 if (!NT_SUCCESS(Status))
533 goto ExitWithError;
534
535 BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
536 PCI_WHICHSPACE_CONFIG,
537 &PciConfig,
538 0,
539 PCI_COMMON_HDR_LENGTH);
540
541 if (BytesRead != PCI_COMMON_HDR_LENGTH)
542 {
543 DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n");
544 goto ExitWithError;
545 }
546
547 FdoExtension->VendorID = PciConfig.VendorID;
548 FdoExtension->DeviceID = PciConfig.DeviceID;
549 FdoExtension->RevisionID = PciConfig.RevisionID;
550 FdoExtension->ProgIf = PciConfig.ProgIf;
551 FdoExtension->SubClass = PciConfig.SubClass;
552 FdoExtension->BaseClass = PciConfig.BaseClass;
553
554 RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
555
556 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
557 DeviceDescription.Master = TRUE;
558 DeviceDescription.ScatterGather = TRUE;
559 DeviceDescription.Dma32BitAddresses = TRUE;
560 DeviceDescription.InterfaceType = PCIBus;
561 DeviceDescription.DmaWidth = Width32Bits;
562 DeviceDescription.DmaSpeed = Compatible;
563 DeviceDescription.MaximumLength = MAXULONG;
564
565 DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice,
566 &DeviceDescription,
567 &FdoExtension->NumberMapRegs);
568
569 FdoExtension->DmaAdapter = DmaAdapter;
570
571 if (!DmaAdapter)
572 {
573 DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n");
574 Status = STATUS_INSUFFICIENT_RESOURCES;
575 goto ExitWithError;
576 }
577
578 Status = USBPORT_CreateWorkerThread(FdoDevice);
579 if (!NT_SUCCESS(Status))
580 goto ExitWithError;
581
582 Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities);
583 if (!NT_SUCCESS(Status))
584 goto ExitWithError;
585
586 FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16;
587 FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF;
588
589 Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
590 DevicePropertyBusNumber,
591 sizeof(ULONG),
592 &FdoExtension->BusNumber,
593 &ResultLength);
594
595 if (!NT_SUCCESS(Status))
596 goto ExitWithError;
597
598 KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock);
599 KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock);
600 KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock);
601 KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock);
602 KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock);
603 KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock);
604 KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock);
605 KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock);
606 KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock);
607 KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock);
608 KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock);
609 KeInitializeSpinLock(&FdoExtension->MiniportSpinLock);
610 KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock);
611 KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
612 KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
613 KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
614 KeInitializeSpinLock(&FdoExtension->TtSpinLock);
615
616 KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
617
618 KeInitializeDpc(&FdoExtension->TransferFlushDpc,
619 USBPORT_TransferFlushDpc,
620 FdoDevice);
621
622 KeInitializeDpc(&FdoExtension->WorkerRequestDpc,
623 USBPORT_WorkerRequestDpc,
624 FdoDevice);
625
626 KeInitializeDpc(&FdoExtension->HcWakeDpc,
627 USBPORT_HcWakeDpc,
628 FdoDevice);
629
630 IoCsqInitialize(&FdoExtension->IdleIoCsq,
631 USBPORT_InsertIdleIrp,
632 USBPORT_RemoveIdleIrp,
633 USBPORT_PeekNextIdleIrp,
634 USBPORT_AcquireIdleLock,
635 USBPORT_ReleaseIdleLock,
636 USBPORT_CompleteCanceledIdleIrp);
637
638 IoCsqInitialize(&FdoExtension->BadRequestIoCsq,
639 USBPORT_InsertBadRequest,
640 USBPORT_RemoveBadRequest,
641 USBPORT_PeekNextBadRequest,
642 USBPORT_AcquireBadRequestLock,
643 USBPORT_ReleaseBadRequestLock,
644 USBPORT_CompleteCanceledBadRequest);
645
646 FdoExtension->IsrDpcCounter = -1;
647 FdoExtension->IsrDpcHandlerCounter = -1;
648 FdoExtension->IdleLockCounter = -1;
649 FdoExtension->BadRequestLockCounter = -1;
650 FdoExtension->ChirpRootPortLock = -1;
651
652 FdoExtension->RHInitCallBackLock = 0;
653
654 FdoExtension->UsbAddressBitMap[0] = 1;
655 FdoExtension->UsbAddressBitMap[1] = 0;
656 FdoExtension->UsbAddressBitMap[2] = 0;
657 FdoExtension->UsbAddressBitMap[3] = 0;
658
659 USBPORT_GetDefaultBIOSx(FdoDevice,
660 &FdoExtension->UsbBIOSx,
661 &DisableSelectiveSuspend,
662 &DisableCcDetect,
663 &IdleEpSupport,
664 &IdleEpSupportEx,
665 &SoftRetry);
666
667 if (DisableSelectiveSuspend)
668 FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS;
669
670 if (!DisableSelectiveSuspend &&
671 USBPORT_IsSelectiveSuspendEnabled(FdoDevice))
672 {
673 FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
674 }
675
676 MiniportFlags = Packet->MiniPortFlags;
677
678 if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING)
679 FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING;
680
681 if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT)
682 FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT;
683
684 if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS)
685 FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) |
686 USBPORT_FLAG_BIOS_DISABLE_SS;
687
688 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
689 TRUE,
690 REG_DWORD,
691 L"EnIdleEndpointSupport",
692 &IdleEpSupport,
693 sizeof(IdleEpSupport));
694
695 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
696 TRUE,
697 REG_DWORD,
698 L"EnIdleEndpointSupportEx",
699 &IdleEpSupportEx,
700 sizeof(IdleEpSupportEx));
701
702 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
703 TRUE,
704 REG_DWORD,
705 L"EnSoftRetry",
706 &SoftRetry,
707 sizeof(SoftRetry));
708
709 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
710 FdoExtension->CommonExtension.LowerPdoDevice,
711 TRUE,
712 L"CommonBuffer2GBLimit",
713 sizeof(L"CommonBuffer2GBLimit"),
714 &Limit2GB,
715 sizeof(Limit2GB));
716
717 FdoExtension->CommonBufferLimit = (Limit2GB != 0);
718
719 if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR &&
720 FdoExtension->SubClass == PCI_SUBCLASS_SB_USB &&
721 FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI)
722 {
723 Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion);
724
725 if (!NT_SUCCESS(Status))
726 {
727 if (IsCompanion)
728 {
729 FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC;
730 }
731 else
732 {
733 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
734 }
735 }
736 }
737
738 if (DisableCcDetect)
739 {
740 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
741 }
742
743 TotalBusBandwidth = Packet->MiniPortBusBandwidth;
744 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
745
746 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
747 FdoExtension->CommonExtension.LowerPdoDevice,
748 TRUE,
749 L"TotalBusBandwidth",
750 sizeof(L"TotalBusBandwidth"),
751 &TotalBusBandwidth,
752 sizeof(TotalBusBandwidth));
753
754 if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth)
755 {
756 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
757 }
758
759 for (ix = 0; ix < USB2_FRAMES; ix++)
760 {
761 FdoExtension->Bandwidth[ix] = FdoExtension->TotalBusBandwidth -
762 FdoExtension->TotalBusBandwidth / 10;
763 }
764
765 FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
766 sizeof(USBPORT_IRP_TABLE),
767 USB_PORT_TAG);
768
769 if (!FdoExtension->ActiveIrpTable)
770 {
771 DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n");
772 goto ExitWithError;
773 }
774
775 RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE));
776
777 FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool,
778 sizeof(USBPORT_IRP_TABLE),
779 USB_PORT_TAG);
780
781 if (!FdoExtension->PendingIrpTable)
782 {
783 DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n");
784 goto ExitWithError;
785 }
786
787 RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE));
788
789 Status = IoConnectInterrupt(&FdoExtension->InterruptObject,
790 USBPORT_InterruptService,
791 (PVOID)FdoDevice,
792 0,
793 UsbPortResources->InterruptVector,
794 UsbPortResources->InterruptLevel,
795 UsbPortResources->InterruptLevel,
796 UsbPortResources->InterruptMode,
797 UsbPortResources->ShareVector,
798 UsbPortResources->InterruptAffinity,
799 0);
800
801
802 if (!NT_SUCCESS(Status))
803 {
804 DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n");
805 goto ExitWithError;
806 }
807
808 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
809
810 if (Packet->MiniPortExtensionSize)
811 {
812 RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
813 }
814
815 if (Packet->MiniPortResourcesSize)
816 {
817 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
818 Packet->MiniPortResourcesSize);
819
820 if (!HeaderBuffer)
821 {
822 DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n");
823 Status = STATUS_INSUFFICIENT_RESOURCES;
824 goto ExitWithError;
825 }
826
827 UsbPortResources->StartVA = HeaderBuffer->VirtualAddress;
828 UsbPortResources->StartPA = HeaderBuffer->PhysicalAddress;
829
830 FdoExtension->MiniPortCommonBuffer = HeaderBuffer;
831 }
832 else
833 {
834 FdoExtension->MiniPortCommonBuffer = NULL;
835 }
836
837 MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt,
838 UsbPortResources);
839
840 if (UsbPortResources->LegacySupport)
841 {
842 FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT;
843 LegacyBIOS = 1;
844 }
845 else
846 {
847 LegacyBIOS = 0;
848 }
849
850 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
851 FALSE,
852 REG_DWORD,
853 L"DetectedLegacyBIOS",
854 &LegacyBIOS,
855 sizeof(LegacyBIOS));
856
857 if (MiniPortStatus)
858 {
859 DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n",
860 MiniPortStatus);
861
862 if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED)
863 {
864 IoDisconnectInterrupt(FdoExtension->InterruptObject);
865 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
866 }
867
868 if (FdoExtension->MiniPortCommonBuffer)
869 {
870 USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer);
871 FdoExtension->MiniPortCommonBuffer = NULL;
872 }
873
874 goto ExitWithError;
875 }
876 else
877 {
878 FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED;
879 USBPORT_MiniportInterrupts(FdoDevice, TRUE);
880 }
881
882 FdoExtension->TimerValue = 500;
883 USBPORT_StartTimer((PVOID)FdoDevice, 500);
884
885 Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice,
886 FdoDevice,
887 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
888 TRUE);
889
890 if (!NT_SUCCESS(Status))
891 {
892 DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n");
893 goto ExitWithError;
894 }
895
896 USBPORT_CreateLegacySymbolicLink(FdoDevice);
897
898 FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED;
899
900 DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status);
901 return Status;
902
903 ExitWithError:
904 USBPORT_StopDevice(FdoDevice);
905
906 DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status);
907 return Status;
908 }
909
910 NTSTATUS
911 NTAPI
912 USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice,
913 IN PIRP Irp,
914 IN PUSBPORT_RESOURCES UsbPortResources)
915 {
916 PCM_RESOURCE_LIST AllocatedResourcesTranslated;
917 PCM_PARTIAL_RESOURCE_LIST ResourceList;
918 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
919 PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL;
920 PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL;
921 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
922 PIO_STACK_LOCATION IoStack;
923 ULONG ix;
924 NTSTATUS Status = STATUS_SUCCESS;
925
926 DPRINT("USBPORT_ParseResources: ... \n");
927
928 IoStack = IoGetCurrentIrpStackLocation(Irp);
929 AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
930
931 if (AllocatedResourcesTranslated)
932 {
933 RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES));
934
935 ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList;
936
937 PartialDescriptor = &ResourceList->PartialDescriptors[0];
938
939 for (ix = 0; ix < ResourceList->Count; ++ix)
940 {
941 if (PartialDescriptor->Type == CmResourceTypePort)
942 {
943 if (!PortDescriptor)
944 PortDescriptor = PartialDescriptor;
945 }
946 else if (PartialDescriptor->Type == CmResourceTypeInterrupt)
947 {
948 if (!InterruptDescriptor)
949 InterruptDescriptor = PartialDescriptor;
950 }
951 else if (PartialDescriptor->Type == CmResourceTypeMemory)
952 {
953 if (!MemoryDescriptor)
954 MemoryDescriptor = PartialDescriptor;
955 }
956
957 PartialDescriptor += 1;
958 }
959
960 if (PortDescriptor)
961 {
962 if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO)
963 {
964 UsbPortResources->ResourceBase = (PVOID)(ULONG_PTR)PortDescriptor->u.Port.Start.QuadPart;
965 }
966 else
967 {
968 UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start,
969 PortDescriptor->u.Port.Length,
970 0);
971 }
972
973 UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length;
974
975 if (UsbPortResources->ResourceBase)
976 {
977 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT;
978 }
979 else
980 {
981 Status = STATUS_NONE_MAPPED;
982 }
983 }
984
985 if (MemoryDescriptor && NT_SUCCESS(Status))
986 {
987 UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length;
988
989 UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start,
990 MemoryDescriptor->u.Memory.Length,
991 0);
992
993 if (UsbPortResources->ResourceBase)
994 {
995 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY;
996 }
997 else
998 {
999 Status = STATUS_NONE_MAPPED;
1000 }
1001 }
1002
1003 if (InterruptDescriptor && NT_SUCCESS(Status))
1004 {
1005 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT;
1006
1007 UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
1008 UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
1009 UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
1010
1011 UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition ==
1012 CmResourceShareShared;
1013
1014 UsbPortResources->InterruptMode = InterruptDescriptor->Flags ==
1015 CM_RESOURCE_INTERRUPT_LATCHED;
1016 }
1017 }
1018 else
1019 {
1020 Status = STATUS_NONE_MAPPED;
1021 }
1022
1023 return Status;
1024 }
1025
1026 NTSTATUS
1027 NTAPI
1028 USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice,
1029 OUT PDEVICE_OBJECT *RootHubPdo)
1030 {
1031 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1032 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1033 UNICODE_STRING DeviceName;
1034 ULONG DeviceNumber = 0;
1035 PDEVICE_OBJECT DeviceObject = NULL;
1036 WCHAR CharDeviceName[64];
1037 NTSTATUS Status = STATUS_SUCCESS;
1038
1039 DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n",
1040 FdoDevice,
1041 RootHubPdo);
1042
1043 FdoExtension = FdoDevice->DeviceExtension;
1044
1045 do
1046 {
1047 RtlStringCbPrintfW(CharDeviceName,
1048 sizeof(CharDeviceName),
1049 L"\\Device\\USBPDO-%d",
1050 DeviceNumber);
1051
1052 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1053
1054 DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName);
1055
1056 Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject,
1057 sizeof(USBPORT_RHDEVICE_EXTENSION),
1058 &DeviceName,
1059 FILE_DEVICE_BUS_EXTENDER,
1060 0,
1061 FALSE,
1062 &DeviceObject);
1063
1064 ++DeviceNumber;
1065 }
1066 while (Status == STATUS_OBJECT_NAME_COLLISION);
1067
1068 if (!NT_SUCCESS(Status))
1069 {
1070 *RootHubPdo = NULL;
1071 DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n");
1072 return Status;
1073 }
1074
1075 if (DeviceObject)
1076 {
1077 PdoExtension = DeviceObject->DeviceExtension;
1078
1079 RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION));
1080
1081 PdoExtension->CommonExtension.SelfDevice = DeviceObject;
1082 PdoExtension->CommonExtension.IsPDO = TRUE;
1083
1084 PdoExtension->FdoDevice = FdoDevice;
1085 PdoExtension->PdoNameNumber = DeviceNumber;
1086
1087 USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject);
1088
1089 DeviceObject->StackSize = FdoDevice->StackSize;
1090
1091 DeviceObject->Flags |= DO_POWER_PAGABLE;
1092 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1093 }
1094 else
1095 {
1096 Status = STATUS_UNSUCCESSFUL;
1097 }
1098
1099 if (!NT_SUCCESS(Status))
1100 *RootHubPdo = NULL;
1101 else
1102 *RootHubPdo = DeviceObject;
1103
1104 DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject);
1105 return Status;
1106 }
1107
1108 NTSTATUS
1109 NTAPI
1110 USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice,
1111 IN PIRP Irp)
1112 {
1113 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1114 PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1115 PUSBPORT_REGISTRATION_PACKET Packet;
1116 PUSBPORT_RESOURCES UsbPortResources;
1117 PIO_STACK_LOCATION IoStack;
1118 UCHAR Minor;
1119 KEVENT Event;
1120 NTSTATUS Status;
1121 DEVICE_RELATION_TYPE RelationType;
1122 PDEVICE_RELATIONS DeviceRelations;
1123 PDEVICE_OBJECT RootHubPdo;
1124
1125 FdoExtension = FdoDevice->DeviceExtension;
1126 FdoCommonExtension = &FdoExtension->CommonExtension;
1127 UsbPortResources = &FdoExtension->UsbPortResources;
1128 Packet = &FdoExtension->MiniPortInterface->Packet;
1129
1130 IoStack = IoGetCurrentIrpStackLocation(Irp);
1131 Minor = IoStack->MinorFunction;
1132
1133 DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor);
1134
1135 RelationType = IoStack->Parameters.QueryDeviceRelations.Type;
1136
1137 switch (Minor)
1138 {
1139 case IRP_MN_START_DEVICE:
1140 DPRINT("IRP_MN_START_DEVICE\n");
1141
1142 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1143
1144 IoCopyCurrentIrpStackLocationToNext(Irp);
1145
1146 IoSetCompletionRoutine(Irp,
1147 USBPORT_FdoStartCompletion,
1148 &Event,
1149 TRUE,
1150 TRUE,
1151 TRUE);
1152
1153 Status = IoCallDriver(FdoCommonExtension->LowerDevice,
1154 Irp);
1155
1156 if (Status == STATUS_PENDING)
1157 {
1158 KeWaitForSingleObject(&Event,
1159 Suspended,
1160 KernelMode,
1161 FALSE,
1162 NULL);
1163
1164 Status = Irp->IoStatus.Status;
1165 }
1166
1167 if (!NT_SUCCESS(Status))
1168 {
1169 goto Exit;
1170 }
1171
1172 Status = USBPORT_ParseResources(FdoDevice,
1173 Irp,
1174 UsbPortResources);
1175
1176 if (!NT_SUCCESS(Status))
1177 {
1178 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1179 goto Exit;
1180 }
1181
1182 Status = USBPORT_StartDevice(FdoDevice, UsbPortResources);
1183
1184 if (!NT_SUCCESS(Status))
1185 {
1186 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1187 goto Exit;
1188 }
1189
1190 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT;
1191 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED;
1192
1193 FdoCommonExtension->DevicePowerState = PowerDeviceD0;
1194
1195 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1196 {
1197 USBPORT_AddUSB2Fdo(FdoDevice);
1198 }
1199 else
1200 {
1201 USBPORT_AddUSB1Fdo(FdoDevice);
1202 }
1203
1204 Exit:
1205 Irp->IoStatus.Status = Status;
1206 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1207 return Status;
1208
1209 case IRP_MN_QUERY_REMOVE_DEVICE:
1210 DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
1211 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1212 {
1213 DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n");
1214 }
1215
1216 Irp->IoStatus.Status = STATUS_SUCCESS;
1217 goto ForwardIrp;
1218
1219 case IRP_MN_REMOVE_DEVICE:
1220 DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n");
1221 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED;
1222
1223 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED &&
1224 !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT))
1225 {
1226 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1227 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1228 }
1229
1230 Irp->IoStatus.Status = STATUS_SUCCESS;
1231 IoSkipCurrentIrpStackLocation(Irp);
1232 Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1233
1234 IoDetachDevice(FdoCommonExtension->LowerDevice);
1235
1236 RootHubPdo = FdoExtension->RootHubPdo;
1237
1238 IoDeleteDevice(FdoDevice);
1239
1240 if (RootHubPdo)
1241 {
1242 IoDeleteDevice(RootHubPdo);
1243 }
1244
1245 return Status;
1246
1247 case IRP_MN_CANCEL_REMOVE_DEVICE:
1248 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1249 Irp->IoStatus.Status = STATUS_SUCCESS;
1250 goto ForwardIrp;
1251
1252 case IRP_MN_STOP_DEVICE:
1253 DPRINT("IRP_MN_STOP_DEVICE\n");
1254 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED)
1255 {
1256 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1257
1258 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED;
1259 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1260 }
1261
1262 Irp->IoStatus.Status = STATUS_SUCCESS;
1263 goto ForwardIrp;
1264
1265 case IRP_MN_QUERY_STOP_DEVICE:
1266 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1267 Irp->IoStatus.Status = STATUS_SUCCESS;
1268 goto ForwardIrp;
1269
1270 case IRP_MN_CANCEL_STOP_DEVICE:
1271 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1272 Irp->IoStatus.Status = STATUS_SUCCESS;
1273 goto ForwardIrp;
1274
1275 case IRP_MN_QUERY_DEVICE_RELATIONS:
1276 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1277 if (RelationType == BusRelations)
1278 {
1279 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1280 sizeof(DEVICE_RELATIONS),
1281 USB_PORT_TAG);
1282
1283 if (!DeviceRelations)
1284 {
1285 Status = STATUS_INSUFFICIENT_RESOURCES;
1286 Irp->IoStatus.Status = Status;
1287 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1288 return Status;
1289 }
1290
1291 DeviceRelations->Count = 0;
1292 DeviceRelations->Objects[0] = NULL;
1293
1294 if (!FdoExtension->RootHubPdo)
1295 {
1296 Status = USBPORT_CreatePdo(FdoDevice,
1297 &FdoExtension->RootHubPdo);
1298
1299 if (!NT_SUCCESS(Status))
1300 {
1301 ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG);
1302 goto ForwardIrp;
1303 }
1304 }
1305 else
1306 {
1307 Status = STATUS_SUCCESS;
1308 }
1309
1310 DeviceRelations->Count = 1;
1311 DeviceRelations->Objects[0] = FdoExtension->RootHubPdo;
1312
1313 ObReferenceObject(FdoExtension->RootHubPdo);
1314 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1315 }
1316 else
1317 {
1318 if (RelationType == RemovalRelations)
1319 {
1320 DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n");
1321 }
1322
1323 goto ForwardIrp;
1324 }
1325
1326 Irp->IoStatus.Status = Status;
1327 goto ForwardIrp;
1328
1329 case IRP_MN_QUERY_INTERFACE:
1330 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1331 goto ForwardIrp;
1332
1333 case IRP_MN_QUERY_CAPABILITIES:
1334 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1335 goto ForwardIrp;
1336
1337 case IRP_MN_QUERY_RESOURCES:
1338 DPRINT("IRP_MN_QUERY_RESOURCES\n");
1339 goto ForwardIrp;
1340
1341 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1342 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1343 goto ForwardIrp;
1344
1345 case IRP_MN_QUERY_DEVICE_TEXT:
1346 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1347 goto ForwardIrp;
1348
1349 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1350 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1351 goto ForwardIrp;
1352
1353 case IRP_MN_READ_CONFIG:
1354 DPRINT("IRP_MN_READ_CONFIG\n");
1355 goto ForwardIrp;
1356
1357 case IRP_MN_WRITE_CONFIG:
1358 DPRINT("IRP_MN_WRITE_CONFIG\n");
1359 goto ForwardIrp;
1360
1361 case IRP_MN_EJECT:
1362 DPRINT("IRP_MN_EJECT\n");
1363 goto ForwardIrp;
1364
1365 case IRP_MN_SET_LOCK:
1366 DPRINT("IRP_MN_SET_LOCK\n");
1367 goto ForwardIrp;
1368
1369 case IRP_MN_QUERY_ID:
1370 DPRINT("IRP_MN_QUERY_ID\n");
1371 goto ForwardIrp;
1372
1373 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1374 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1375 goto ForwardIrp;
1376
1377 case IRP_MN_QUERY_BUS_INFORMATION:
1378 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1379 goto ForwardIrp;
1380
1381 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1382 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1383 goto ForwardIrp;
1384
1385 case IRP_MN_SURPRISE_REMOVAL:
1386 DPRINT1("IRP_MN_SURPRISE_REMOVAL\n");
1387 if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED))
1388 {
1389 USBPORT_InvalidateControllerHandler(FdoDevice,
1390 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
1391 }
1392 goto ForwardIrp;
1393
1394 default:
1395 DPRINT("unknown IRP_MN_???\n");
1396 ForwardIrp:
1397 /* forward irp to next device object */
1398 IoSkipCurrentIrpStackLocation(Irp);
1399 break;
1400 }
1401
1402 return IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1403 }
1404
1405 PVOID
1406 NTAPI
1407 USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice,
1408 IN USHORT VendorID,
1409 IN USHORT DeviceID,
1410 IN USHORT RevisionID)
1411 {
1412 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1413 PUSBPORT_REGISTRATION_PACKET Packet;
1414 PVOID Id;
1415 WCHAR Buffer[300] = {0};
1416 SIZE_T Length = 0;
1417 size_t Remaining = sizeof(Buffer);
1418 PWCHAR EndBuffer;
1419
1420 FdoExtension = FdoDevice->DeviceExtension;
1421 Packet = &FdoExtension->MiniPortInterface->Packet;
1422
1423 DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n",
1424 FdoDevice,
1425 Packet->MiniPortFlags);
1426
1427 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1428 {
1429 RtlStringCbPrintfExW(Buffer,
1430 Remaining,
1431 &EndBuffer,
1432 &Remaining,
1433 0,
1434 L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x",
1435 VendorID,
1436 DeviceID,
1437 RevisionID);
1438
1439 EndBuffer++;
1440 Remaining -= sizeof(UNICODE_NULL);
1441
1442 RtlStringCbPrintfExW(EndBuffer,
1443 Remaining,
1444 &EndBuffer,
1445 &Remaining,
1446 0,
1447 L"USB\\ROOT_HUB20&VID%04x&PID%04x",
1448 VendorID,
1449 DeviceID);
1450
1451 EndBuffer++;
1452 Remaining -= sizeof(UNICODE_NULL);
1453
1454 RtlStringCbPrintfExW(EndBuffer,
1455 Remaining,
1456 NULL,
1457 &Remaining,
1458 0,
1459 L"USB\\ROOT_HUB20");
1460 }
1461 else
1462 {
1463 RtlStringCbPrintfExW(Buffer,
1464 Remaining,
1465 &EndBuffer,
1466 &Remaining,
1467 0,
1468 L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x",
1469 VendorID,
1470 DeviceID,
1471 RevisionID);
1472
1473 EndBuffer++;
1474 Remaining -= sizeof(UNICODE_NULL);
1475
1476 RtlStringCbPrintfExW(EndBuffer,
1477 Remaining,
1478 &EndBuffer,
1479 &Remaining,
1480 0,
1481 L"USB\\ROOT_HUB&VID%04x&PID%04x",
1482 VendorID,
1483 DeviceID);
1484
1485 EndBuffer++;
1486 Remaining -= sizeof(UNICODE_NULL);
1487
1488 RtlStringCbPrintfExW(EndBuffer,
1489 Remaining,
1490 NULL,
1491 &Remaining,
1492 0,
1493 L"USB\\ROOT_HUB");
1494 }
1495
1496 Length = (sizeof(Buffer) - Remaining + 2 * sizeof(UNICODE_NULL));
1497
1498 /* for debug only */
1499 if (FALSE)
1500 {
1501 DPRINT("Hardware IDs:\n");
1502 USBPORT_DumpingIDs(Buffer);
1503 }
1504
1505 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG);
1506
1507 if (!Id)
1508 return NULL;
1509
1510 RtlMoveMemory(Id, Buffer, Length);
1511
1512 return Id;
1513 }
1514
1515 NTSTATUS
1516 NTAPI
1517 USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice,
1518 IN PIRP Irp)
1519 {
1520 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1521 PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension;
1522 PDEVICE_OBJECT FdoDevice;
1523 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1524 PIO_STACK_LOCATION IoStack;
1525 UCHAR Minor;
1526 NTSTATUS Status;
1527 PPNP_BUS_INFORMATION BusInformation;
1528 PDEVICE_CAPABILITIES DeviceCapabilities;
1529
1530 PdoExtension = PdoDevice->DeviceExtension;
1531 PdoCommonExtension = &PdoExtension->CommonExtension;
1532
1533 FdoDevice = PdoExtension->FdoDevice;
1534 FdoExtension = FdoDevice->DeviceExtension;
1535
1536 IoStack = IoGetCurrentIrpStackLocation(Irp);
1537 Minor = IoStack->MinorFunction;
1538
1539 Status = Irp->IoStatus.Status;
1540
1541 DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor);
1542
1543 switch (Minor)
1544 {
1545 case IRP_MN_START_DEVICE:
1546 DPRINT("IRP_MN_START_DEVICE\n");
1547
1548 Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice);
1549
1550 if (NT_SUCCESS(Status))
1551 {
1552 Status = USBPORT_RegisterDeviceInterface(PdoDevice,
1553 PdoDevice,
1554 &GUID_DEVINTERFACE_USB_HUB,
1555 TRUE);
1556
1557 if (NT_SUCCESS(Status))
1558 {
1559 PdoCommonExtension->DevicePowerState = PowerDeviceD0;
1560 PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED;
1561 }
1562 }
1563
1564 break;
1565
1566 case IRP_MN_QUERY_REMOVE_DEVICE:
1567 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n");
1568 Status = STATUS_SUCCESS;
1569 break;
1570
1571 case IRP_MN_REMOVE_DEVICE:
1572 DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n");
1573 //USBPORT_StopRootHub();
1574 Status = STATUS_SUCCESS;
1575 break;
1576
1577 case IRP_MN_CANCEL_REMOVE_DEVICE:
1578 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1579 Status = STATUS_SUCCESS;
1580 break;
1581
1582 case IRP_MN_STOP_DEVICE:
1583 DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n");
1584 //USBPORT_StopRootHub();
1585 Status = STATUS_SUCCESS;
1586 break;
1587
1588 case IRP_MN_QUERY_STOP_DEVICE:
1589 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1590 Status = STATUS_SUCCESS;
1591 break;
1592
1593 case IRP_MN_CANCEL_STOP_DEVICE:
1594 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1595 Status = STATUS_SUCCESS;
1596 break;
1597
1598 case IRP_MN_QUERY_DEVICE_RELATIONS:
1599 {
1600 PDEVICE_RELATIONS DeviceRelations;
1601
1602 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1603 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1604 {
1605 break;
1606 }
1607
1608 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1609 sizeof(DEVICE_RELATIONS),
1610 USB_PORT_TAG);
1611
1612 if (!DeviceRelations)
1613 {
1614 Status = STATUS_INSUFFICIENT_RESOURCES;
1615 Irp->IoStatus.Information = 0;
1616 break;
1617 }
1618
1619 DeviceRelations->Count = 1;
1620 DeviceRelations->Objects[0] = PdoDevice;
1621
1622 ObReferenceObject(PdoDevice);
1623
1624 Status = STATUS_SUCCESS;
1625 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1626 break;
1627 }
1628
1629 case IRP_MN_QUERY_INTERFACE:
1630 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1631 Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp);
1632 break;
1633
1634 case IRP_MN_QUERY_CAPABILITIES:
1635 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1636
1637 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
1638
1639 RtlCopyMemory(DeviceCapabilities,
1640 &PdoExtension->Capabilities,
1641 sizeof(DEVICE_CAPABILITIES));
1642
1643 Status = STATUS_SUCCESS;
1644 break;
1645
1646 case IRP_MN_QUERY_RESOURCES:
1647 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n");
1648 break;
1649
1650 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1651 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1652 break;
1653
1654 case IRP_MN_QUERY_DEVICE_TEXT:
1655 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1656 break;
1657
1658 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1659 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1660 break;
1661
1662 case IRP_MN_READ_CONFIG:
1663 DPRINT("IRP_MN_READ_CONFIG\n");
1664 ASSERT(FALSE);
1665 break;
1666
1667 case IRP_MN_WRITE_CONFIG:
1668 DPRINT("IRP_MN_WRITE_CONFIG\n");
1669 ASSERT(FALSE);
1670 break;
1671
1672 case IRP_MN_EJECT:
1673 DPRINT("IRP_MN_EJECT\n");
1674 ASSERT(FALSE);
1675 break;
1676
1677 case IRP_MN_SET_LOCK:
1678 DPRINT("IRP_MN_SET_LOCK\n");
1679 ASSERT(FALSE);
1680 break;
1681
1682 case IRP_MN_QUERY_ID:
1683 {
1684 ULONG IdType;
1685 LONG Length;
1686 WCHAR Buffer[64] = {0};
1687 PVOID Id;
1688
1689 Status = STATUS_SUCCESS;
1690 IdType = IoStack->Parameters.QueryId.IdType;
1691
1692 DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType);
1693
1694 if (IdType == BusQueryDeviceID)
1695 {
1696 PUSBPORT_REGISTRATION_PACKET Packet;
1697 Packet = &FdoExtension->MiniPortInterface->Packet;
1698
1699 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1700 {
1701 RtlStringCbPrintfW(Buffer,
1702 sizeof(Buffer),
1703 L"USB\\ROOT_HUB20");
1704 }
1705 else
1706 {
1707 RtlStringCbPrintfW(Buffer,
1708 sizeof(Buffer),
1709 L"USB\\ROOT_HUB");
1710 }
1711
1712 Length = (LONG)(wcslen(Buffer) + 1);
1713
1714 Id = ExAllocatePoolWithTag(PagedPool,
1715 Length * sizeof(WCHAR),
1716 USB_PORT_TAG);
1717
1718 if (Id)
1719 {
1720 RtlZeroMemory(Id, Length * sizeof(WCHAR));
1721 RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer);
1722
1723 DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n",
1724 Id,
1725 Length);
1726 }
1727
1728 Irp->IoStatus.Information = (ULONG_PTR)Id;
1729 break;
1730 }
1731
1732 if (IdType == BusQueryHardwareIDs)
1733 {
1734 Id = USBPORT_GetDeviceHwIds(FdoDevice,
1735 FdoExtension->VendorID,
1736 FdoExtension->DeviceID,
1737 FdoExtension->RevisionID);
1738
1739 Irp->IoStatus.Information = (ULONG_PTR)Id;
1740 break;
1741 }
1742
1743 if (IdType == BusQueryCompatibleIDs ||
1744 IdType == BusQueryInstanceID)
1745 {
1746 Irp->IoStatus.Information = 0;
1747 break;
1748 }
1749
1750 /* IdType == BusQueryDeviceSerialNumber */
1751 Status = Irp->IoStatus.Status;
1752 break;
1753 }
1754
1755 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1756 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1757 Status = STATUS_SUCCESS;
1758 break;
1759
1760 case IRP_MN_QUERY_BUS_INFORMATION:
1761 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1762
1763 /* Allocate buffer for bus information */
1764 BusInformation = ExAllocatePoolWithTag(PagedPool,
1765 sizeof(PNP_BUS_INFORMATION),
1766 USB_PORT_TAG);
1767
1768 if (!BusInformation)
1769 {
1770 /* No memory */
1771 Status = STATUS_INSUFFICIENT_RESOURCES;
1772 break;
1773 }
1774
1775 RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION));
1776
1777 /* Copy BUS GUID */
1778 RtlMoveMemory(&BusInformation->BusTypeGuid,
1779 &GUID_BUS_TYPE_USB,
1780 sizeof(GUID));
1781
1782 /* Set bus type */
1783 BusInformation->LegacyBusType = PNPBus;
1784 BusInformation->BusNumber = 0;
1785
1786 Status = STATUS_SUCCESS;
1787 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
1788 break;
1789
1790 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1791 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1792 break;
1793
1794 case IRP_MN_SURPRISE_REMOVAL:
1795 DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n");
1796 Status = STATUS_SUCCESS;
1797 break;
1798
1799 default:
1800 DPRINT("unknown IRP_MN_???\n");
1801 break;
1802 }
1803
1804 Irp->IoStatus.Status = Status;
1805 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1806 return Status;
1807 }