[NTOS:IO][NTOS:PNP] Add PiActionAddBootDevices device action
[reactos.git] / drivers / usb / usbhub / usbhub.c
1 /*
2 * PROJECT: ReactOS USB Hub Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBHub main driver functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbhub.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NDEBUG_USBHUB_SCE
14 #define NDEBUG_USBHUB_PNP
15 #include "dbg_uhub.h"
16
17 #include <ntddstor.h>
18
19 PWSTR GenericUSBDeviceString = NULL;
20
21 NTSTATUS
22 NTAPI
23 USBH_Wait(IN ULONG Milliseconds)
24 {
25 LARGE_INTEGER Interval;
26
27 DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds);
28 Interval.QuadPart = -10000LL * Milliseconds - ((ULONGLONG)KeQueryTimeIncrement() - 1);
29 return KeDelayExecutionThread(KernelMode, FALSE, &Interval);
30 }
31
32 NTSTATUS
33 NTAPI
34 USBH_GetConfigValue(IN PWSTR ValueName,
35 IN ULONG ValueType,
36 IN PVOID ValueData,
37 IN ULONG ValueLength,
38 IN PVOID Context,
39 IN PVOID EntryContext)
40 {
41 NTSTATUS Status = STATUS_SUCCESS;
42
43 DPRINT("USBHUB_GetConfigValue: ... \n");
44
45 if (ValueType == REG_BINARY)
46 {
47 *(PUCHAR)EntryContext = *(PUCHAR)ValueData;
48 }
49 else if (ValueType == REG_DWORD)
50 {
51 *(PULONG)EntryContext = *(PULONG)ValueData;
52 }
53 else
54 {
55 Status = STATUS_INVALID_PARAMETER;
56 }
57
58 return Status;
59 }
60
61 VOID
62 NTAPI
63 USBH_CompleteIrp(IN PIRP Irp,
64 IN NTSTATUS CompleteStatus)
65 {
66 if (CompleteStatus != STATUS_SUCCESS)
67 {
68 DPRINT1("USBH_CompleteIrp: Irp - %p, CompleteStatus - %X\n",
69 Irp,
70 CompleteStatus);
71 }
72
73 Irp->IoStatus.Status = CompleteStatus;
74 IoCompleteRequest(Irp, IO_NO_INCREMENT);
75 }
76
77 NTSTATUS
78 NTAPI
79 USBH_PassIrp(IN PDEVICE_OBJECT DeviceObject,
80 IN PIRP Irp)
81 {
82 DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n",
83 DeviceObject,
84 Irp);
85
86 IoSkipCurrentIrpStackLocation(Irp);
87 return IoCallDriver(DeviceObject, Irp);
88 }
89
90 NTSTATUS
91 NTAPI
92 USBH_SyncIrpComplete(IN PDEVICE_OBJECT DeviceObject,
93 IN PIRP Irp,
94 IN PVOID Context)
95 {
96 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
97 KIRQL OldIrql;
98 BOOLEAN TimerCancelled;
99
100 DPRINT("USBH_SyncIrpComplete: ... \n");
101
102 HubTimeoutContext = Context;
103
104 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql);
105 HubTimeoutContext->IsNormalCompleted = TRUE;
106 TimerCancelled = KeCancelTimer(&HubTimeoutContext->UrbTimeoutTimer);
107 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql);
108
109 if (TimerCancelled)
110 {
111 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent,
112 EVENT_INCREMENT,
113 FALSE);
114 }
115
116 return STATUS_SUCCESS;
117 }
118
119 BOOLEAN
120 NTAPI
121 IsBitSet(IN PUCHAR BitMapAddress,
122 IN USHORT Bit)
123 {
124 BOOLEAN IsSet;
125
126 IsSet = (BitMapAddress[Bit / 8] & (1 << (Bit & 7))) != 0;
127 DPRINT("IsBitSet: Bit - %lX, IsSet - %x\n", Bit, IsSet);
128 return IsSet;
129 }
130
131 PUSBHUB_PORT_PDO_EXTENSION
132 NTAPI
133 PdoExt(IN PDEVICE_OBJECT DeviceObject)
134 {
135 PVOID PdoExtension;
136
137 DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject);
138
139 if (DeviceObject)
140 {
141 PdoExtension = DeviceObject->DeviceExtension;
142 }
143 else
144 {
145 PdoExtension = NULL;
146 }
147
148 return (PUSBHUB_PORT_PDO_EXTENSION)PdoExtension;
149 }
150
151 NTSTATUS
152 NTAPI
153 USBH_WriteFailReasonID(IN PDEVICE_OBJECT DeviceObject,
154 IN ULONG FailReason)
155 {
156 NTSTATUS Status;
157 HANDLE KeyHandle;
158 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FailReasonID");
159
160 DPRINT("USBH_WriteFailReason: ID - %x\n", FailReason);
161
162 Status = IoOpenDeviceRegistryKey(DeviceObject,
163 PLUGPLAY_REGKEY_DEVICE,
164 STANDARD_RIGHTS_ALL,
165 &KeyHandle);
166
167 if (NT_SUCCESS(Status))
168 {
169 ZwSetValueKey(KeyHandle,
170 &ValueName,
171 0,
172 REG_DWORD,
173 &FailReason,
174 sizeof(FailReason));
175
176 ZwClose(KeyHandle);
177 }
178
179 return Status;
180 }
181
182 VOID
183 NTAPI
184 USBH_UrbTimeoutDPC(IN PKDPC Dpc,
185 IN PVOID DeferredContext,
186 IN PVOID SystemArgument1,
187 IN PVOID SystemArgument2)
188 {
189 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
190 KIRQL OldIrql;
191 BOOL IsCompleted;
192
193 DPRINT("USBH_TimeoutDPC ... \n");
194
195 HubTimeoutContext = DeferredContext;
196
197 KeAcquireSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, &OldIrql);
198 IsCompleted = HubTimeoutContext->IsNormalCompleted;
199 KeReleaseSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock, OldIrql);
200
201 if (!IsCompleted)
202 {
203 IoCancelIrp(HubTimeoutContext->Irp);
204 }
205
206 KeSetEvent(&HubTimeoutContext->UrbTimeoutEvent,
207 EVENT_INCREMENT,
208 FALSE);
209 }
210
211 NTSTATUS
212 NTAPI
213 USBH_SetPdoRegistryParameter(IN PDEVICE_OBJECT DeviceObject,
214 IN PCWSTR ValueName,
215 IN PVOID Data,
216 IN ULONG DataSize,
217 IN ULONG Type,
218 IN ULONG DevInstKeyType)
219 {
220 NTSTATUS Status;
221 UNICODE_STRING ValueNameString;
222 HANDLE KeyHandle;
223
224 DPRINT("USBH_SetPdoRegistryParameter ... \n");
225
226 RtlInitUnicodeString(&ValueNameString, ValueName);
227
228 Status = IoOpenDeviceRegistryKey(DeviceObject,
229 DevInstKeyType,
230 STANDARD_RIGHTS_ALL,
231 &KeyHandle);
232
233 if (NT_SUCCESS(Status))
234 {
235 ZwSetValueKey(KeyHandle,
236 &ValueNameString,
237 0,
238 Type,
239 Data,
240 DataSize);
241
242 ZwClose(KeyHandle);
243 }
244
245 return Status;
246 }
247
248 NTSTATUS
249 NTAPI
250 USBH_SyncSubmitUrb(IN PDEVICE_OBJECT DeviceObject,
251 IN PURB Urb)
252 {
253 KEVENT Event;
254 IO_STATUS_BLOCK IoStatusBlock;
255 PIRP Irp;
256 PIO_STACK_LOCATION IoStack;
257 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
258 BOOLEAN IsWaitTimeout = FALSE;
259 LARGE_INTEGER DueTime;
260 NTSTATUS Status;
261
262 DPRINT("USBH_SyncSubmitUrb: ... \n");
263
264 Urb->UrbHeader.UsbdDeviceHandle = NULL;
265
266 KeInitializeEvent(&Event, NotificationEvent, FALSE);
267
268 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
269 DeviceObject,
270 NULL,
271 0,
272 NULL,
273 0,
274 TRUE,
275 &Event,
276 &IoStatusBlock);
277
278 if (!Irp)
279 {
280 return STATUS_INSUFFICIENT_RESOURCES;
281 }
282
283 IoStack = IoGetNextIrpStackLocation(Irp);
284 IoStack->Parameters.Others.Argument1 = Urb;
285
286 HubTimeoutContext = ExAllocatePoolWithTag(NonPagedPool,
287 sizeof(USBHUB_URB_TIMEOUT_CONTEXT),
288 USB_HUB_TAG);
289
290 if (HubTimeoutContext)
291 {
292 RtlZeroMemory(HubTimeoutContext, sizeof(USBHUB_URB_TIMEOUT_CONTEXT));
293
294 HubTimeoutContext->Irp = Irp;
295 HubTimeoutContext->IsNormalCompleted = FALSE;
296
297 KeInitializeEvent(&HubTimeoutContext->UrbTimeoutEvent,
298 NotificationEvent,
299 FALSE);
300
301 KeInitializeSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock);
302 KeInitializeTimer(&HubTimeoutContext->UrbTimeoutTimer);
303
304 KeInitializeDpc(&HubTimeoutContext->UrbTimeoutDPC,
305 USBH_UrbTimeoutDPC,
306 HubTimeoutContext);
307
308 DueTime.QuadPart = -5000 * 10000; // Timeout 5 sec.
309
310 KeSetTimer(&HubTimeoutContext->UrbTimeoutTimer,
311 DueTime,
312 &HubTimeoutContext->UrbTimeoutDPC);
313
314 IoSetCompletionRoutine(Irp,
315 USBH_SyncIrpComplete,
316 HubTimeoutContext,
317 TRUE,
318 TRUE,
319 TRUE);
320
321 IsWaitTimeout = TRUE;
322 }
323
324 Status = IoCallDriver(DeviceObject, Irp);
325
326 if (Status == STATUS_PENDING)
327 {
328 KeWaitForSingleObject(&Event,
329 Suspended,
330 KernelMode,
331 FALSE,
332 NULL);
333 }
334 else
335 {
336 IoStatusBlock.Status = Status;
337 }
338
339 if (IsWaitTimeout)
340 {
341 KeWaitForSingleObject(&HubTimeoutContext->UrbTimeoutEvent,
342 Suspended,
343 KernelMode,
344 FALSE,
345 NULL);
346
347 ExFreePoolWithTag(HubTimeoutContext, USB_HUB_TAG);
348 }
349
350 return IoStatusBlock.Status;
351 }
352
353 NTSTATUS
354 NTAPI
355 USBH_FdoSyncSubmitUrb(IN PDEVICE_OBJECT FdoDevice,
356 IN PURB Urb)
357 {
358 PUSBHUB_FDO_EXTENSION HubExtension;
359
360 DPRINT("USBH_FdoSyncSubmitUrb: FdoDevice - %p, Urb - %p\n",
361 FdoDevice,
362 Urb);
363
364 HubExtension = FdoDevice->DeviceExtension;
365 return USBH_SyncSubmitUrb(HubExtension->LowerDevice, Urb);
366 }
367
368 NTSTATUS
369 NTAPI
370 USBH_Transact(IN PUSBHUB_FDO_EXTENSION HubExtension,
371 IN PVOID TransferBuffer,
372 IN ULONG BufferLen,
373 IN BOOLEAN IsDeviceToHost,
374 IN USHORT Function,
375 IN BM_REQUEST_TYPE RequestType,
376 IN UCHAR Request,
377 IN USHORT RequestValue,
378 IN USHORT RequestIndex)
379 {
380 struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb;
381 ULONG TransferFlags;
382 PVOID Buffer = NULL;
383 ULONG Length;
384 NTSTATUS Status;
385
386 DPRINT("USBH_Transact: ... \n");
387
388 if (BufferLen)
389 {
390 Length = ALIGN_DOWN_BY(BufferLen + sizeof(ULONG), sizeof(ULONG));
391
392 Buffer = ExAllocatePoolWithTag(NonPagedPool, Length, USB_HUB_TAG);
393
394 if (!Buffer)
395 {
396 return STATUS_INSUFFICIENT_RESOURCES;
397 }
398
399 RtlZeroMemory(Buffer, Length);
400 }
401
402 Urb = ExAllocatePoolWithTag(NonPagedPool,
403 sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
404 USB_HUB_TAG);
405
406 if (!Urb)
407 {
408 if (Buffer)
409 {
410 ExFreePoolWithTag(Buffer, USB_HUB_TAG);
411 }
412
413 return STATUS_INSUFFICIENT_RESOURCES;
414 }
415
416 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
417
418 if (IsDeviceToHost)
419 {
420 if (BufferLen)
421 {
422 RtlZeroMemory(TransferBuffer, BufferLen);
423 }
424
425 TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
426 }
427 else
428 {
429 if (BufferLen)
430 {
431 RtlCopyMemory(Buffer, TransferBuffer, BufferLen);
432 }
433
434 TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
435 }
436
437 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
438 Urb->Hdr.Function = Function;
439 Urb->Hdr.UsbdDeviceHandle = NULL;
440
441 Urb->TransferFlags = TransferFlags;
442 Urb->TransferBuffer = BufferLen != 0 ? Buffer : NULL;
443 Urb->TransferBufferLength = BufferLen;
444 Urb->TransferBufferMDL = NULL;
445 Urb->UrbLink = NULL;
446
447 Urb->RequestTypeReservedBits = RequestType.B;
448 Urb->Request = Request;
449 Urb->Value = RequestValue;
450 Urb->Index = RequestIndex;
451
452 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice, (PURB)Urb);
453
454 if (IsDeviceToHost && BufferLen)
455 {
456 RtlCopyMemory(TransferBuffer, Buffer, BufferLen);
457 }
458
459 if (Buffer)
460 {
461 ExFreePoolWithTag(Buffer, USB_HUB_TAG);
462 }
463
464 ExFreePoolWithTag(Urb, USB_HUB_TAG);
465
466 return Status;
467 }
468
469 NTSTATUS
470 NTAPI
471 USBH_SyncResetPort(IN PUSBHUB_FDO_EXTENSION HubExtension,
472 IN USHORT Port)
473 {
474 USB_PORT_STATUS_AND_CHANGE PortStatus;
475 KEVENT Event;
476 LARGE_INTEGER Timeout;
477 ULONG ResetRetry = 0;
478 NTSTATUS Status;
479
480 DPRINT("USBH_SyncResetPort: Port - %x\n", Port);
481
482 InterlockedIncrement(&HubExtension->PendingRequestCount);
483
484 KeWaitForSingleObject(&HubExtension->HubPortSemaphore,
485 Executive,
486 KernelMode,
487 FALSE,
488 NULL);
489
490 Status = USBH_SyncGetPortStatus(HubExtension,
491 Port,
492 &PortStatus,
493 sizeof(USB_PORT_STATUS_AND_CHANGE));
494
495 if (NT_SUCCESS(Status) &&
496 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0))
497 {
498 Status = STATUS_UNSUCCESSFUL;
499 goto Exit;
500 }
501
502 HubExtension->HubFlags |= USBHUB_FDO_FLAG_RESET_PORT_LOCK;
503
504 while (TRUE)
505 {
506 BM_REQUEST_TYPE RequestType;
507
508 KeInitializeEvent(&Event, NotificationEvent, FALSE);
509
510 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
511 &Event);
512
513 RequestType.B = 0;
514 RequestType.Recipient = BMREQUEST_TO_DEVICE;
515 RequestType.Type = BMREQUEST_CLASS;
516 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
517
518 Status = USBH_Transact(HubExtension,
519 NULL,
520 0,
521 BMREQUEST_HOST_TO_DEVICE,
522 URB_FUNCTION_CLASS_OTHER,
523 RequestType,
524 USB_REQUEST_SET_FEATURE,
525 USBHUB_FEATURE_PORT_RESET,
526 Port);
527
528 Timeout.QuadPart = -5000 * 10000;
529
530 if (!NT_SUCCESS(Status))
531 {
532 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
533 NULL);
534
535 USBH_Wait(10);
536 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
537
538 goto Exit;
539 }
540
541 Status = KeWaitForSingleObject(&Event,
542 Suspended,
543 KernelMode,
544 FALSE,
545 &Timeout);
546
547 if (Status != STATUS_TIMEOUT)
548 {
549 break;
550 }
551
552 Status = USBH_SyncGetPortStatus(HubExtension,
553 Port,
554 &PortStatus,
555 sizeof(USB_PORT_STATUS_AND_CHANGE));
556
557 if (!NT_SUCCESS(Status) ||
558 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) ||
559 ResetRetry >= USBHUB_RESET_PORT_MAX_RETRY)
560 {
561 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
562 NULL);
563
564 USBH_Wait(10);
565 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
566
567 Status = STATUS_DEVICE_DATA_ERROR;
568 goto Exit;
569 }
570
571 ResetRetry++;
572 }
573
574 Status = USBH_SyncGetPortStatus(HubExtension,
575 Port,
576 &PortStatus,
577 sizeof(USB_PORT_STATUS_AND_CHANGE));
578
579 if ((PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) &&
580 NT_SUCCESS(Status) &&
581 HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)
582 {
583 Status = STATUS_DEVICE_DATA_ERROR;
584 }
585
586 USBH_Wait(10);
587 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
588
589 Exit:
590
591 KeReleaseSemaphore(&HubExtension->HubPortSemaphore,
592 LOW_REALTIME_PRIORITY,
593 1,
594 FALSE);
595
596 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
597 {
598 KeSetEvent(&HubExtension->PendingRequestEvent,
599 EVENT_INCREMENT,
600 FALSE);
601 }
602
603 return Status;
604 }
605
606 NTSTATUS
607 NTAPI
608 USBH_GetDeviceType(IN PUSBHUB_FDO_EXTENSION HubExtension,
609 IN PUSB_DEVICE_HANDLE DeviceHandle,
610 OUT USB_DEVICE_TYPE * OutDeviceType)
611 {
612 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation;
613 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
614 SIZE_T DeviceInformationBufferLength;
615 USB_DEVICE_TYPE DeviceType = Usb11Device;
616 ULONG dummy;
617 NTSTATUS Status;
618
619 DPRINT("USBH_GetDeviceType: ... \n");
620
621 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
622
623 if (!QueryDeviceInformation)
624 {
625 DPRINT1("USBH_GetDeviceType: no QueryDeviceInformation()\n");
626 return STATUS_NOT_IMPLEMENTED;
627 }
628
629 DeviceInformationBufferLength = sizeof(USB_DEVICE_INFORMATION_0);
630
631 while (TRUE)
632 {
633 DeviceInfo = ExAllocatePoolWithTag(PagedPool,
634 DeviceInformationBufferLength,
635 USB_HUB_TAG);
636
637 if (!DeviceInfo)
638 {
639 DPRINT1("USBH_GetDeviceType: ExAllocatePoolWithTag() failed\n");
640 Status = STATUS_INSUFFICIENT_RESOURCES;
641 break;
642 }
643
644 RtlZeroMemory(DeviceInfo, DeviceInformationBufferLength);
645
646 DeviceInfo->InformationLevel = 0;
647
648 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
649 DeviceHandle,
650 DeviceInfo,
651 DeviceInformationBufferLength,
652 &dummy);
653
654 if (Status != STATUS_BUFFER_TOO_SMALL)
655 {
656 if (NT_SUCCESS(Status))
657 {
658 DeviceType = DeviceInfo->DeviceType;
659 }
660
661 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
662 break;
663 }
664
665 DeviceInformationBufferLength = DeviceInfo->ActualLength;
666 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
667 }
668
669 if (OutDeviceType)
670 {
671 *OutDeviceType = DeviceType;
672 DPRINT("USBH_GetDeviceType: DeviceType - %x\n", DeviceType);
673 }
674
675 return Status;
676 }
677
678 NTSTATUS
679 NTAPI
680 USBHUB_GetExtendedHubInfo(IN PUSBHUB_FDO_EXTENSION HubExtension,
681 IN PUSB_EXTHUB_INFORMATION_0 HubInfoBuffer)
682 {
683 PUSB_BUSIFFN_GET_EXTENDED_HUB_INFO GetExtendedHubInformation;
684 ULONG dummy = 0;
685
686 DPRINT("USBHUB_GetExtendedHubInfo: ... \n");
687
688 GetExtendedHubInformation = HubExtension->BusInterface.GetExtendedHubInformation;
689
690 return GetExtendedHubInformation(HubExtension->BusInterface.BusContext,
691 HubExtension->LowerPDO,
692 HubInfoBuffer,
693 sizeof(USB_EXTHUB_INFORMATION_0),
694 &dummy);
695 }
696
697 PUSBHUB_FDO_EXTENSION
698 NTAPI
699 USBH_GetRootHubExtension(IN PUSBHUB_FDO_EXTENSION HubExtension)
700 {
701 PDEVICE_OBJECT Device;
702 PUSBHUB_FDO_EXTENSION RootHubExtension;
703
704 DPRINT("USBH_GetRootHubExtension: HubExtension - %p\n", HubExtension);
705
706 RootHubExtension = HubExtension;
707
708 if (HubExtension->LowerPDO != HubExtension->RootHubPdo)
709 {
710 Device = HubExtension->RootHubPdo;
711
712 do
713 {
714 Device = Device->AttachedDevice;
715 }
716 while (Device->DriverObject != HubExtension->Common.SelfDevice->DriverObject);
717
718 RootHubExtension = Device->DeviceExtension;
719 }
720
721 DPRINT("USBH_GetRootHubExtension: RootHubExtension - %p\n", RootHubExtension);
722
723 return RootHubExtension;
724 }
725
726 NTSTATUS
727 NTAPI
728 USBH_SyncGetRootHubPdo(IN PDEVICE_OBJECT DeviceObject,
729 IN OUT PDEVICE_OBJECT * OutPdo1,
730 IN OUT PDEVICE_OBJECT * OutPdo2)
731 {
732 KEVENT Event;
733 IO_STATUS_BLOCK IoStatusBlock;
734 PIRP Irp;
735 PIO_STACK_LOCATION IoStack;
736 NTSTATUS Status;
737
738 DPRINT("USBH_SyncGetRootHubPdo: ... \n");
739
740 KeInitializeEvent(&Event, NotificationEvent, FALSE);
741
742 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
743 DeviceObject,
744 NULL,
745 0,
746 NULL,
747 0,
748 TRUE,
749 &Event,
750 &IoStatusBlock);
751
752 if (!Irp)
753 {
754 return STATUS_INSUFFICIENT_RESOURCES;
755 }
756
757 IoStack = IoGetNextIrpStackLocation(Irp);
758 IoStack->Parameters.Others.Argument1 = OutPdo1;
759 IoStack->Parameters.Others.Argument2 = OutPdo2;
760
761 Status = IoCallDriver(DeviceObject, Irp);
762
763 if (Status == STATUS_PENDING)
764 {
765 KeWaitForSingleObject(&Event,
766 Suspended,
767 KernelMode,
768 FALSE,
769 NULL);
770 }
771 else
772 {
773 IoStatusBlock.Status = Status;
774 }
775
776 return IoStatusBlock.Status;
777 }
778
779 NTSTATUS
780 NTAPI
781 USBH_SyncGetHubCount(IN PDEVICE_OBJECT DeviceObject,
782 IN OUT PULONG OutHubCount)
783 {
784 KEVENT Event;
785 IO_STATUS_BLOCK IoStatusBlock;
786 PIRP Irp;
787 PIO_STACK_LOCATION IoStack;
788 NTSTATUS Status;
789
790 DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount);
791
792 KeInitializeEvent(&Event, NotificationEvent, FALSE);
793
794 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_HUB_COUNT,
795 DeviceObject,
796 NULL,
797 0,
798 NULL,
799 0,
800 TRUE,
801 &Event,
802 &IoStatusBlock);
803
804 if (!Irp)
805 {
806 return STATUS_INSUFFICIENT_RESOURCES;
807 }
808
809 IoStack = IoGetNextIrpStackLocation(Irp);
810 IoStack->Parameters.Others.Argument1 = OutHubCount;
811
812 Status = IoCallDriver(DeviceObject, Irp);
813
814 if (Status == STATUS_PENDING)
815 {
816 KeWaitForSingleObject(&Event,
817 Suspended,
818 KernelMode,
819 FALSE,
820 NULL);
821 }
822 else
823 {
824 IoStatusBlock.Status = Status;
825 }
826
827 return IoStatusBlock.Status;
828 }
829
830 PUSB_DEVICE_HANDLE
831 NTAPI
832 USBH_SyncGetDeviceHandle(IN PDEVICE_OBJECT DeviceObject)
833 {
834 PIRP Irp;
835 KEVENT Event;
836 IO_STATUS_BLOCK IoStatusBlock;
837 PUSB_DEVICE_HANDLE DeviceHandle = NULL;
838 PIO_STACK_LOCATION IoStack;
839
840 DPRINT("USBH_SyncGetDeviceHandle: ... \n");
841
842 KeInitializeEvent(&Event, NotificationEvent, FALSE);
843
844 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
845 DeviceObject,
846 NULL,
847 0,
848 NULL,
849 0,
850 TRUE,
851 &Event,
852 &IoStatusBlock);
853
854 if (!Irp)
855 {
856 DPRINT1("USBH_SyncGetDeviceHandle: Irp - NULL!\n");
857 return NULL;
858 }
859
860 IoStack = IoGetNextIrpStackLocation(Irp);
861 IoStack->Parameters.Others.Argument1 = &DeviceHandle;
862
863 if (IoCallDriver(DeviceObject, Irp) == STATUS_PENDING)
864 {
865 KeWaitForSingleObject(&Event,
866 Suspended,
867 KernelMode,
868 FALSE,
869 NULL);
870 }
871
872 return DeviceHandle;
873 }
874
875 NTSTATUS
876 NTAPI
877 USBH_GetDeviceDescriptor(IN PDEVICE_OBJECT DeviceObject,
878 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor)
879 {
880 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
881 NTSTATUS Status;
882
883 DPRINT("USBH_GetDeviceDescriptor: ... \n");
884
885 Urb = ExAllocatePoolWithTag(NonPagedPool,
886 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
887 USB_HUB_TAG);
888
889 if (!Urb)
890 {
891 DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n");
892 return STATUS_INSUFFICIENT_RESOURCES;
893 }
894
895 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
896
897 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
898 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
899
900 Urb->TransferBufferLength = sizeof(USB_DEVICE_DESCRIPTOR);
901 Urb->TransferBuffer = HubDeviceDescriptor;
902 Urb->DescriptorType = USB_DEVICE_DESCRIPTOR_TYPE;
903
904 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
905
906 ExFreePoolWithTag(Urb, USB_HUB_TAG);
907
908 return Status;
909 }
910
911 NTSTATUS
912 NTAPI
913 USBH_SyncGetDeviceConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject,
914 IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
915 IN ULONG NumberOfBytes,
916 IN PULONG OutLength)
917 {
918 PCOMMON_DEVICE_EXTENSION DeviceExtension;
919 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
920 NTSTATUS Status;
921
922 DPRINT("USBH_SyncGetDeviceConfigurationDescriptor: ... \n");
923
924 DeviceExtension = DeviceObject->DeviceExtension;
925
926 if (OutLength)
927 {
928 *OutLength = 0;
929 }
930
931 Urb = ExAllocatePoolWithTag(NonPagedPool,
932 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
933 USB_HUB_TAG);
934
935 if (!Urb)
936 {
937 return STATUS_INSUFFICIENT_RESOURCES;
938 }
939
940 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
941
942 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
943 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
944
945 Urb->TransferBufferLength = NumberOfBytes;
946 Urb->TransferBuffer = ConfigDescriptor;
947 Urb->DescriptorType = USB_CONFIGURATION_DESCRIPTOR_TYPE;
948
949 if (DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_HUB ||
950 DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_PARENT)
951 {
952 Status = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
953 }
954 else
955 {
956 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb);
957 }
958
959 if (OutLength)
960 {
961 *OutLength = Urb->TransferBufferLength;
962 }
963
964 if (Urb)
965 {
966 ExFreePoolWithTag(Urb, USB_HUB_TAG);
967 }
968
969 return Status;
970 }
971
972 NTSTATUS
973 NTAPI
974 USBH_GetConfigurationDescriptor(IN PDEVICE_OBJECT DeviceObject,
975 IN PUSB_CONFIGURATION_DESCRIPTOR * OutDescriptor)
976 {
977 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
978 ULONG ReturnedLen;
979 SIZE_T DescriptorLen;
980 NTSTATUS Status;
981
982 DPRINT("USBH_GetConfigurationDescriptor: ... \n");
983
984 DescriptorLen = MAXUCHAR;
985
986 while (TRUE)
987 {
988 ConfigDescriptor = ExAllocatePoolWithTag(NonPagedPool,
989 DescriptorLen,
990 USB_HUB_TAG);
991
992 if (!ConfigDescriptor)
993 {
994 Status = STATUS_INSUFFICIENT_RESOURCES;
995 break;
996 }
997
998 Status = USBH_SyncGetDeviceConfigurationDescriptor(DeviceObject,
999 ConfigDescriptor,
1000 DescriptorLen,
1001 &ReturnedLen);
1002
1003 if (ReturnedLen < sizeof(USB_CONFIGURATION_DESCRIPTOR))
1004 {
1005 Status = STATUS_DEVICE_DATA_ERROR;
1006 }
1007
1008 if (!NT_SUCCESS(Status))
1009 {
1010 break;
1011 }
1012
1013 *OutDescriptor = ConfigDescriptor;
1014
1015 if (ConfigDescriptor->wTotalLength <= DescriptorLen)
1016 {
1017 break;
1018 }
1019
1020 DescriptorLen = ConfigDescriptor->wTotalLength;
1021
1022 ExFreePool(ConfigDescriptor);
1023 *OutDescriptor = NULL;
1024 }
1025
1026 if (NT_SUCCESS(Status))
1027 {
1028 if (ReturnedLen < ConfigDescriptor->wTotalLength)
1029 {
1030 Status = STATUS_DEVICE_DATA_ERROR;
1031 }
1032 }
1033 else
1034 {
1035 if (ConfigDescriptor)
1036 {
1037 ExFreePool(ConfigDescriptor);
1038 }
1039
1040 *OutDescriptor = NULL;
1041 }
1042
1043 return Status;
1044 }
1045
1046 NTSTATUS
1047 NTAPI
1048 USBH_SyncGetHubDescriptor(IN PUSBHUB_FDO_EXTENSION HubExtension)
1049 {
1050 PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo;
1051 ULONG NumberPorts;
1052 PUSBHUB_PORT_DATA PortData;
1053 USHORT RequestValue;
1054 ULONG NumberOfBytes;
1055 NTSTATUS Status;
1056 PUSB_HUB_DESCRIPTOR HubDescriptor = NULL;
1057 ULONG ix;
1058 ULONG Retry;
1059
1060 DPRINT("USBH_SyncGetHubDescriptor: ... \n");
1061
1062 ExtendedHubInfo = ExAllocatePoolWithTag(NonPagedPool,
1063 sizeof(USB_EXTHUB_INFORMATION_0),
1064 USB_HUB_TAG);
1065
1066 if (!ExtendedHubInfo)
1067 {
1068 Status = STATUS_INSUFFICIENT_RESOURCES;
1069 goto ErrorExit;
1070 }
1071
1072 RtlZeroMemory(ExtendedHubInfo, sizeof(USB_EXTHUB_INFORMATION_0));
1073
1074 Status = USBHUB_GetExtendedHubInfo(HubExtension, ExtendedHubInfo);
1075
1076 if (!NT_SUCCESS(Status))
1077 {
1078 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1079 ExtendedHubInfo = NULL;
1080 }
1081
1082 NumberOfBytes = sizeof(USB_HUB_DESCRIPTOR);
1083
1084 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1085 NumberOfBytes,
1086 USB_HUB_TAG);
1087
1088 if (!HubDescriptor)
1089 {
1090 Status = STATUS_INSUFFICIENT_RESOURCES;
1091 goto ErrorExit;
1092 }
1093
1094 RtlZeroMemory(HubDescriptor, NumberOfBytes);
1095
1096 RequestValue = 0;
1097 Retry = 0;
1098
1099 while (TRUE)
1100 {
1101 while (Retry <= 5)
1102 {
1103 BM_REQUEST_TYPE RequestType;
1104
1105 RequestType.B = 0;
1106 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1107 RequestType.Type = BMREQUEST_STANDARD;
1108 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1109
1110 Status = USBH_Transact(HubExtension,
1111 HubDescriptor,
1112 NumberOfBytes,
1113 BMREQUEST_DEVICE_TO_HOST,
1114 URB_FUNCTION_CLASS_DEVICE,
1115 RequestType,
1116 USB_REQUEST_GET_DESCRIPTOR,
1117 RequestValue,
1118 0);
1119
1120 if (NT_SUCCESS(Status))
1121 {
1122 break;
1123 }
1124
1125 RequestValue = 0x2900; // Hub DescriptorType - 0x29
1126
1127 Retry++;
1128 }
1129
1130 if (HubDescriptor->bDescriptorLength <= NumberOfBytes)
1131 {
1132 break;
1133 }
1134
1135 NumberOfBytes = HubDescriptor->bDescriptorLength;
1136 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG);
1137
1138 if (Retry >= 5)
1139 {
1140 Status = STATUS_DEVICE_DATA_ERROR;
1141 HubDescriptor = NULL;
1142 goto ErrorExit;
1143 }
1144
1145 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1146 NumberOfBytes,
1147 USB_HUB_TAG);
1148
1149 if (!HubDescriptor)
1150 {
1151 Status = STATUS_INSUFFICIENT_RESOURCES;
1152 goto ErrorExit;
1153 }
1154
1155 RtlZeroMemory(HubDescriptor, NumberOfBytes);
1156 }
1157
1158 NumberPorts = HubDescriptor->bNumberOfPorts;
1159
1160 if (HubExtension->PortData)
1161 {
1162 PortData = HubExtension->PortData;
1163
1164 for (ix = 0; ix < NumberPorts; ix++)
1165 {
1166 PortData[ix].PortStatus.AsUlong32 = 0;
1167
1168 if (ExtendedHubInfo)
1169 {
1170 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes;
1171 }
1172 else
1173 {
1174 PortData[ix].PortAttributes = 0;
1175 }
1176
1177 PortData[ix].ConnectionStatus = NoDeviceConnected;
1178
1179 if (PortData[ix].DeviceObject != NULL)
1180 {
1181 PortData[ix].ConnectionStatus = DeviceConnected;
1182 }
1183 }
1184 }
1185 else
1186 {
1187 PortData = NULL;
1188
1189 if (HubDescriptor->bNumberOfPorts)
1190 {
1191 PortData = ExAllocatePoolWithTag(NonPagedPool,
1192 NumberPorts * sizeof(USBHUB_PORT_DATA),
1193 USB_HUB_TAG);
1194 }
1195
1196 if (!PortData)
1197 {
1198 Status = STATUS_INSUFFICIENT_RESOURCES;
1199 goto ErrorExit;
1200 }
1201
1202 RtlZeroMemory(PortData, NumberPorts * sizeof(USBHUB_PORT_DATA));
1203
1204 for (ix = 0; ix < NumberPorts; ix++)
1205 {
1206 PortData[ix].ConnectionStatus = NoDeviceConnected;
1207
1208 if (ExtendedHubInfo)
1209 {
1210 PortData[ix].PortAttributes = ExtendedHubInfo->Port[ix].PortAttributes;
1211 }
1212 }
1213 }
1214
1215 if (!NT_SUCCESS(Status))
1216 {
1217 goto ErrorExit;
1218 }
1219
1220 HubExtension->HubDescriptor = HubDescriptor;
1221
1222 HubExtension->PortData = PortData;
1223
1224 if (ExtendedHubInfo)
1225 {
1226 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1227 }
1228
1229 return Status;
1230
1231 ErrorExit:
1232
1233 if (HubDescriptor)
1234 {
1235 ExFreePoolWithTag(HubDescriptor, USB_HUB_TAG);
1236 }
1237
1238 if (ExtendedHubInfo)
1239 {
1240 ExFreePoolWithTag(ExtendedHubInfo, USB_HUB_TAG);
1241 }
1242
1243 return Status;
1244 }
1245
1246 NTSTATUS
1247 NTAPI
1248 USBH_SyncGetStringDescriptor(IN PDEVICE_OBJECT DeviceObject,
1249 IN UCHAR Index,
1250 IN USHORT LanguageId,
1251 IN PUSB_STRING_DESCRIPTOR Descriptor,
1252 IN ULONG NumberOfBytes,
1253 IN PULONG OutLength,
1254 IN BOOLEAN IsValidateLength)
1255 {
1256 struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
1257 ULONG TransferedLength;
1258 NTSTATUS Status;
1259
1260 DPRINT("USBH_SyncGetStringDescriptor: Index - %x, LanguageId - %x\n",
1261 Index,
1262 LanguageId);
1263
1264 Urb = ExAllocatePoolWithTag(NonPagedPool,
1265 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1266 USB_HUB_TAG);
1267
1268 if (!Urb)
1269 {
1270 return STATUS_INSUFFICIENT_RESOURCES;
1271 }
1272
1273 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
1274
1275 Urb->Hdr.Function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
1276 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
1277
1278 Urb->TransferBuffer = Descriptor;
1279 Urb->TransferBufferLength = NumberOfBytes;
1280
1281 Urb->Index = Index;
1282 Urb->DescriptorType = USB_STRING_DESCRIPTOR_TYPE;
1283 Urb->LanguageId = LanguageId;
1284
1285 Status = USBH_SyncSubmitUrb(DeviceObject, (PURB)Urb);
1286
1287 if (!NT_SUCCESS(Status))
1288 {
1289 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1290 return Status;
1291 }
1292
1293 TransferedLength = Urb->TransferBufferLength;
1294
1295 if (TransferedLength > NumberOfBytes)
1296 {
1297 Status = STATUS_DEVICE_DATA_ERROR;
1298 }
1299
1300 if (!NT_SUCCESS(Status))
1301 {
1302 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1303 return Status;
1304 }
1305
1306 if (OutLength)
1307 {
1308 *OutLength = TransferedLength;
1309 }
1310
1311 if (IsValidateLength && TransferedLength != Descriptor->bLength)
1312 {
1313 Status = STATUS_DEVICE_DATA_ERROR;
1314 }
1315
1316 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1317
1318 return Status;
1319 }
1320
1321 NTSTATUS
1322 NTAPI
1323 USBH_SyncGetStatus(IN PDEVICE_OBJECT DeviceObject,
1324 IN PUSHORT OutStatus,
1325 IN USHORT Function,
1326 IN USHORT RequestIndex)
1327 {
1328 struct _URB_CONTROL_GET_STATUS_REQUEST * Urb;
1329 NTSTATUS NtStatus;
1330 USHORT UsbStatus;
1331
1332 DPRINT("USBH_SyncGetStatus: ... \n");
1333
1334 Urb = ExAllocatePoolWithTag(NonPagedPool,
1335 sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST),
1336 USB_HUB_TAG);
1337
1338 if (!Urb)
1339 {
1340 return STATUS_INSUFFICIENT_RESOURCES;
1341 }
1342
1343 RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST));
1344
1345 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST);
1346 Urb->Hdr.Function = Function;
1347
1348 Urb->TransferBuffer = &UsbStatus;
1349 Urb->TransferBufferLength = sizeof(UsbStatus);
1350 Urb->Index = RequestIndex;
1351
1352 NtStatus = USBH_FdoSyncSubmitUrb(DeviceObject, (PURB)Urb);
1353
1354 *OutStatus = UsbStatus;
1355
1356 ExFreePoolWithTag(Urb, USB_HUB_TAG);
1357
1358 return NtStatus;
1359 }
1360
1361 NTSTATUS
1362 NTAPI
1363 USBH_SyncGetHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1364 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus,
1365 IN ULONG Length)
1366 {
1367 BM_REQUEST_TYPE RequestType;
1368
1369 DPRINT("USBH_SyncGetHubStatus\n");
1370
1371 RequestType.B = 0;
1372 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1373 RequestType.Type = BMREQUEST_CLASS;
1374 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1375
1376 return USBH_Transact(HubExtension,
1377 HubStatus,
1378 Length,
1379 BMREQUEST_DEVICE_TO_HOST,
1380 URB_FUNCTION_CLASS_DEVICE,
1381 RequestType,
1382 USB_REQUEST_GET_STATUS,
1383 0,
1384 0);
1385 }
1386
1387 NTSTATUS
1388 NTAPI
1389 USBH_SyncClearHubStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1390 IN USHORT RequestValue)
1391 {
1392 BM_REQUEST_TYPE RequestType;
1393
1394 DPRINT("USBH_SyncClearHubStatus: RequestValue - %x\n", RequestValue);
1395
1396 RequestType.B = 0;
1397 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1398 RequestType.Type = BMREQUEST_CLASS;
1399 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1400
1401 return USBH_Transact(HubExtension,
1402 NULL,
1403 0,
1404 BMREQUEST_HOST_TO_DEVICE,
1405 URB_FUNCTION_CLASS_DEVICE,
1406 RequestType,
1407 USB_REQUEST_CLEAR_FEATURE,
1408 RequestValue,
1409 0);
1410 }
1411
1412 NTSTATUS
1413 NTAPI
1414 USBH_SyncGetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1415 IN USHORT Port,
1416 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus,
1417 IN ULONG Length)
1418 {
1419 BM_REQUEST_TYPE RequestType;
1420
1421 DPRINT("USBH_SyncGetPortStatus: Port - %x\n", Port);
1422
1423 RequestType.B = 0;
1424 RequestType.Recipient = BMREQUEST_TO_OTHER;
1425 RequestType.Type = BMREQUEST_CLASS;
1426 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1427
1428 return USBH_Transact(HubExtension,
1429 PortStatus,
1430 Length,
1431 BMREQUEST_DEVICE_TO_HOST,
1432 URB_FUNCTION_CLASS_OTHER,
1433 RequestType,
1434 USB_REQUEST_GET_STATUS,
1435 0,
1436 Port);
1437 }
1438
1439
1440 NTSTATUS
1441 NTAPI
1442 USBH_SyncClearPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1443 IN USHORT Port,
1444 IN USHORT RequestValue)
1445 {
1446 BM_REQUEST_TYPE RequestType;
1447
1448 DPRINT("USBH_SyncClearPortStatus: Port - %x, RequestValue - %x\n",
1449 Port,
1450 RequestValue);
1451
1452 RequestType.B = 0;
1453 RequestType.Recipient = BMREQUEST_TO_OTHER;
1454 RequestType.Type = BMREQUEST_CLASS;
1455 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1456
1457 return USBH_Transact(HubExtension,
1458 NULL,
1459 0,
1460 BMREQUEST_HOST_TO_DEVICE,
1461 URB_FUNCTION_CLASS_OTHER,
1462 RequestType,
1463 USB_REQUEST_CLEAR_FEATURE,
1464 RequestValue,
1465 Port);
1466 }
1467
1468 NTSTATUS
1469 NTAPI
1470 USBH_SyncPowerOnPort(IN PUSBHUB_FDO_EXTENSION HubExtension,
1471 IN USHORT Port,
1472 IN BOOLEAN IsWait)
1473 {
1474 PUSBHUB_PORT_DATA PortData;
1475 PUSB_HUB_DESCRIPTOR HubDescriptor;
1476 NTSTATUS Status = STATUS_SUCCESS;
1477 BM_REQUEST_TYPE RequestType;
1478 PUSB_PORT_STATUS_AND_CHANGE PortStatus;
1479
1480 DPRINT("USBH_SyncPowerOnPort: Port - %x, IsWait - %x\n", Port, IsWait);
1481
1482 ASSERT(Port > 0);
1483 PortData = &HubExtension->PortData[Port - 1];
1484 PortStatus = &PortData->PortStatus;
1485
1486 if (PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus == 1)
1487 {
1488 return Status;
1489 }
1490
1491 RequestType.B = 0;
1492 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1493 RequestType.Type = BMREQUEST_CLASS;
1494 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1495
1496 Status = USBH_Transact(HubExtension,
1497 NULL,
1498 0,
1499 BMREQUEST_HOST_TO_DEVICE,
1500 URB_FUNCTION_CLASS_OTHER,
1501 RequestType,
1502 USB_REQUEST_SET_FEATURE,
1503 USBHUB_FEATURE_PORT_POWER,
1504 Port);
1505
1506 if (NT_SUCCESS(Status))
1507 {
1508 if (IsWait)
1509 {
1510 HubDescriptor = HubExtension->HubDescriptor;
1511 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood);
1512 }
1513
1514 PortStatus->PortStatus.Usb20PortStatus.CurrentConnectStatus = 1;
1515 }
1516
1517 return Status;
1518 }
1519
1520 NTSTATUS
1521 NTAPI
1522 USBH_SyncPowerOnPorts(IN PUSBHUB_FDO_EXTENSION HubExtension)
1523 {
1524 PUSB_HUB_DESCRIPTOR HubDescriptor;
1525 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1526 USHORT Port;
1527 UCHAR NumberOfPorts;
1528
1529 DPRINT("USBH_SyncPowerOnPorts: ... \n");
1530
1531 HubDescriptor = HubExtension->HubDescriptor;
1532 NumberOfPorts = HubDescriptor->bNumberOfPorts;
1533
1534 for (Port = 1; Port <= NumberOfPorts; ++Port)
1535 {
1536 Status = USBH_SyncPowerOnPort(HubExtension, Port, 0);
1537
1538 if (!NT_SUCCESS(Status))
1539 {
1540 DPRINT1("USBH_SyncPowerOnPorts: USBH_SyncPowerOnPort() failed - %lX\n",
1541 Status);
1542 break;
1543 }
1544 }
1545
1546 USBH_Wait(2 * HubDescriptor->bPowerOnToPowerGood);
1547
1548 return Status;
1549 }
1550
1551 NTSTATUS
1552 NTAPI
1553 USBH_SyncDisablePort(IN PUSBHUB_FDO_EXTENSION HubExtension,
1554 IN USHORT Port)
1555 {
1556 PUSBHUB_PORT_DATA PortData;
1557 NTSTATUS Status;
1558 BM_REQUEST_TYPE RequestType;
1559
1560 DPRINT("USBH_SyncDisablePort ... \n");
1561
1562 PortData = &HubExtension->PortData[Port - 1];
1563
1564 RequestType.B = 0;
1565 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1566 RequestType.Type = BMREQUEST_CLASS;
1567 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1568
1569 Status = USBH_Transact(HubExtension,
1570 NULL,
1571 0,
1572 BMREQUEST_HOST_TO_DEVICE,
1573 URB_FUNCTION_CLASS_OTHER,
1574 RequestType,
1575 USB_REQUEST_CLEAR_FEATURE,
1576 USBHUB_FEATURE_PORT_ENABLE,
1577 Port);
1578
1579 if (NT_SUCCESS(Status))
1580 {
1581 PortData->PortStatus.PortStatus.Usb20PortStatus.PortEnabledDisabled = 0;
1582 }
1583
1584 return Status;
1585 }
1586
1587 BOOLEAN
1588 NTAPI
1589 USBH_HubIsBusPowered(IN PDEVICE_OBJECT DeviceObject,
1590 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor)
1591 {
1592 BOOLEAN Result;
1593 USHORT UsbStatus;
1594 NTSTATUS Status;
1595
1596 DPRINT("USBH_HubIsBusPowered: ... \n");
1597
1598 Status = USBH_SyncGetStatus(DeviceObject,
1599 &UsbStatus,
1600 URB_FUNCTION_GET_STATUS_FROM_DEVICE,
1601 0);
1602
1603 if (!NT_SUCCESS(Status))
1604 {
1605 Result = (HubConfigDescriptor->bmAttributes & USB_CONFIG_POWERED_MASK)
1606 == USB_CONFIG_BUS_POWERED;
1607 }
1608 else
1609 {
1610 Result = (UsbStatus & USB_GETSTATUS_SELF_POWERED) == 0;
1611 }
1612
1613 return Result;
1614 }
1615
1616 NTSTATUS
1617 NTAPI
1618 USBH_ChangeIndicationAckChangeComplete(IN PDEVICE_OBJECT DeviceObject,
1619 IN PIRP Irp,
1620 IN PVOID Context)
1621 {
1622 PUSBHUB_FDO_EXTENSION HubExtension;
1623 PVOID Event;
1624 USHORT Port;
1625
1626 HubExtension = Context;
1627
1628 DPRINT_SCE("USBH_ChangeIndicationAckChangeComplete: ... \n");
1629
1630 ASSERT(HubExtension->Port > 0);
1631 Port = HubExtension->Port - 1;
1632
1633 HubExtension->PortData[Port].PortStatus = HubExtension->PortStatus;
1634
1635 Event = InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
1636 NULL);
1637
1638 if (Event)
1639 {
1640 KeSetEvent(Event, EVENT_INCREMENT, FALSE);
1641 }
1642
1643 USBH_SubmitStatusChangeTransfer(HubExtension);
1644
1645 if (!InterlockedDecrement(&HubExtension->ResetRequestCount))
1646 {
1647 KeSetEvent(&HubExtension->ResetEvent,
1648 EVENT_INCREMENT,
1649 FALSE);
1650 }
1651
1652 return STATUS_MORE_PROCESSING_REQUIRED;
1653 }
1654
1655 NTSTATUS
1656 NTAPI
1657 USBH_ChangeIndicationAckChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1658 IN PIRP Irp,
1659 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb,
1660 IN USHORT Port,
1661 IN USHORT RequestValue)
1662 {
1663 PIO_STACK_LOCATION IoStack;
1664 BM_REQUEST_TYPE RequestType;
1665
1666 DPRINT_SCE("USBH_ChangeIndicationAckChange: ... \n");
1667
1668 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
1669 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER;
1670 Urb->Hdr.UsbdDeviceHandle = NULL;
1671
1672 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK;
1673 Urb->TransferBufferLength = 0;
1674 Urb->TransferBuffer = NULL;
1675 Urb->TransferBufferMDL = NULL;
1676 Urb->UrbLink = NULL;
1677
1678 RequestType.B = 0;
1679 RequestType.Recipient = BMREQUEST_TO_OTHER;
1680 RequestType.Type = BMREQUEST_CLASS;
1681 RequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1682
1683 Urb->RequestTypeReservedBits = RequestType.B;
1684 Urb->Request = USB_REQUEST_CLEAR_FEATURE;
1685 Urb->Index = Port;
1686 Urb->Value = RequestValue;
1687
1688 IoInitializeIrp(Irp,
1689 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1690 HubExtension->LowerDevice->StackSize);
1691
1692 IoStack = IoGetNextIrpStackLocation(Irp);
1693
1694 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1695 IoStack->Parameters.Others.Argument1 = Urb;
1696 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1697
1698 IoSetCompletionRoutine(Irp,
1699 USBH_ChangeIndicationAckChangeComplete,
1700 HubExtension,
1701 TRUE,
1702 TRUE,
1703 TRUE);
1704
1705 return IoCallDriver(HubExtension->LowerDevice, Irp);
1706 }
1707
1708 NTSTATUS
1709 NTAPI
1710 USBH_ChangeIndicationProcessChange(IN PDEVICE_OBJECT DeviceObject,
1711 IN PIRP Irp,
1712 IN PVOID Context)
1713 {
1714 PUSBHUB_FDO_EXTENSION HubExtension;
1715 PUSBHUB_IO_WORK_ITEM WorkItem;
1716 USHORT RequestValue;
1717
1718 HubExtension = Context;
1719
1720 DPRINT_SCE("USBH_ChangeIndicationProcessChange: PortStatus - %lX\n",
1721 HubExtension->PortStatus.AsUlong32);
1722
1723 if ((NT_SUCCESS(Irp->IoStatus.Status) ||
1724 USBD_SUCCESS(HubExtension->SCEWorkerUrb.Hdr.Status)) &&
1725 (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange ||
1726 HubExtension->PortStatus.PortChange.Usb20PortChange.PortEnableDisableChange))
1727 {
1728 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1729 {
1730 KeSetEvent(&HubExtension->PendingRequestEvent,
1731 EVENT_INCREMENT,
1732 FALSE);
1733 }
1734
1735 USBH_FreeWorkItem(HubExtension->WorkItemToQueue);
1736
1737 HubExtension->WorkItemToQueue = NULL;
1738
1739 if (HubExtension->PortStatus.PortChange.Usb20PortChange.ResetChange)
1740 {
1741 RequestValue = USBHUB_FEATURE_C_PORT_RESET;
1742 }
1743 else
1744 {
1745 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE;
1746 }
1747
1748 USBH_ChangeIndicationAckChange(HubExtension,
1749 HubExtension->ResetPortIrp,
1750 &HubExtension->SCEWorkerUrb,
1751 HubExtension->Port,
1752 RequestValue);
1753 }
1754 else
1755 {
1756 ASSERT(HubExtension->WorkItemToQueue != NULL);
1757
1758 WorkItem = HubExtension->WorkItemToQueue;
1759 HubExtension->WorkItemToQueue = NULL;
1760
1761 USBH_QueueWorkItem(HubExtension, WorkItem);
1762 }
1763
1764 return STATUS_MORE_PROCESSING_REQUIRED;
1765 }
1766
1767 NTSTATUS
1768 NTAPI
1769 USBH_ChangeIndicationQueryChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1770 IN PIRP Irp,
1771 IN struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST * Urb,
1772 IN USHORT Port)
1773 {
1774 PUSBHUB_IO_WORK_ITEM WorkItem;
1775 NTSTATUS Status;
1776 PIO_STACK_LOCATION IoStack;
1777 BM_REQUEST_TYPE RequestType;
1778
1779 DPRINT_SCE("USBH_ChangeIndicationQueryChange: Port - %x\n", Port);
1780
1781 InterlockedIncrement(&HubExtension->PendingRequestCount);
1782
1783 if (!Port)
1784 {
1785 ASSERT(HubExtension->WorkItemToQueue != NULL);
1786
1787 WorkItem = HubExtension->WorkItemToQueue;
1788 HubExtension->WorkItemToQueue = NULL;
1789
1790 USBH_QueueWorkItem(HubExtension, WorkItem);
1791
1792 return STATUS_SUCCESS;
1793 }
1794
1795 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
1796 Urb->Hdr.UsbdDeviceHandle = NULL;
1797 Urb->Hdr.Function = URB_FUNCTION_CLASS_OTHER;
1798
1799 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
1800 Urb->TransferBuffer = &HubExtension->PortStatus;
1801 Urb->TransferBufferLength = sizeof(HubExtension->PortStatus);
1802 Urb->TransferBufferMDL = NULL;
1803 Urb->UrbLink = NULL;
1804
1805 RequestType.B = 0;
1806 RequestType.Recipient = BMREQUEST_TO_OTHER;
1807 RequestType.Type = BMREQUEST_CLASS;
1808 RequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1809
1810 Urb->RequestTypeReservedBits = RequestType.B;
1811 Urb->Request = USB_REQUEST_GET_STATUS;
1812 Urb->Value = 0;
1813 Urb->Index = Port;
1814
1815 HubExtension->Port = Port;
1816
1817 IoInitializeIrp(Irp,
1818 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1819 HubExtension->LowerDevice->StackSize);
1820
1821 IoStack = IoGetNextIrpStackLocation(Irp);
1822
1823 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1824 IoStack->Parameters.Others.Argument1 = Urb;
1825 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1826
1827 IoSetCompletionRoutine(Irp,
1828 USBH_ChangeIndicationProcessChange,
1829 HubExtension,
1830 TRUE,
1831 TRUE,
1832 TRUE);
1833
1834 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
1835
1836 return Status;
1837 }
1838
1839 VOID
1840 NTAPI
1841 USBH_ProcessHubStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1842 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
1843 {
1844 USB_HUB_CHANGE HubStatusChange;
1845
1846 DPRINT_SCE("USBH_ProcessHubStateChange: HubStatus - %lx\n", HubStatus->AsUlong32);
1847
1848 HubStatusChange = HubStatus->HubChange;
1849
1850 if (HubStatusChange.LocalPowerChange)
1851 {
1852 DPRINT1("USBH_ProcessHubStateChange: LocalPowerChange\n");
1853 USBH_SyncClearHubStatus(HubExtension,
1854 USBHUB_FEATURE_C_HUB_LOCAL_POWER);
1855 }
1856 else if (HubStatusChange.OverCurrentChange)
1857 {
1858 USBH_SyncClearHubStatus(HubExtension,
1859 USBHUB_FEATURE_C_HUB_OVER_CURRENT);
1860 if (HubStatus->HubStatus.OverCurrent)
1861 {
1862 DPRINT1("USBH_ProcessHubStateChange: OverCurrent UNIMPLEMENTED. FIXME\n");
1863 DbgBreakPoint();
1864 }
1865 }
1866 }
1867
1868 VOID
1869 NTAPI
1870 USBH_ProcessPortStateChange(IN PUSBHUB_FDO_EXTENSION HubExtension,
1871 IN USHORT Port,
1872 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
1873 {
1874 PUSBHUB_PORT_DATA PortData;
1875 USB_20_PORT_CHANGE PortStatusChange;
1876 PDEVICE_OBJECT PortDevice;
1877 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
1878 PVOID SerialNumber;
1879 PVOID DeviceHandle;
1880 USHORT RequestValue;
1881 KIRQL Irql;
1882
1883 DPRINT_SCE("USBH_ProcessPortStateChange ... \n");
1884
1885 ASSERT(Port > 0);
1886 PortData = &HubExtension->PortData[Port - 1];
1887
1888 PortStatusChange = PortStatus->PortChange.Usb20PortChange;
1889
1890 if (PortStatusChange.ConnectStatusChange)
1891 {
1892 PortData->PortStatus = *PortStatus;
1893
1894 USBH_SyncClearPortStatus(HubExtension,
1895 Port,
1896 USBHUB_FEATURE_C_PORT_CONNECTION);
1897
1898 PortData = &HubExtension->PortData[Port - 1];
1899
1900 PortDevice = PortData->DeviceObject;
1901
1902 if (!PortDevice)
1903 {
1904 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1905 return;
1906 }
1907
1908 PortExtension = PortDevice->DeviceExtension;
1909
1910 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_OVERCURRENT_PORT)
1911 {
1912 return;
1913 }
1914
1915 KeAcquireSpinLock(&HubExtension->RelationsWorkerSpinLock, &Irql);
1916
1917 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D3)
1918 {
1919 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql);
1920 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1921 return;
1922 }
1923
1924 PortData->DeviceObject = NULL;
1925 PortData->ConnectionStatus = NoDeviceConnected;
1926
1927 HubExtension->HubFlags |= USBHUB_FDO_FLAG_STATE_CHANGING;
1928
1929 InsertTailList(&HubExtension->PdoList, &PortExtension->PortLink);
1930
1931 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql);
1932
1933 SerialNumber = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
1934 NULL);
1935
1936 if (SerialNumber)
1937 {
1938 ExFreePoolWithTag(SerialNumber, USB_HUB_TAG);
1939 }
1940
1941 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
1942 NULL);
1943
1944 if (DeviceHandle)
1945 {
1946 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
1947 USBH_SyncDisablePort(HubExtension, Port);
1948 }
1949
1950 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
1951 }
1952 else if (PortStatusChange.PortEnableDisableChange)
1953 {
1954 RequestValue = USBHUB_FEATURE_C_PORT_ENABLE;
1955 PortData->PortStatus = *PortStatus;
1956 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue);
1957 return;
1958 }
1959 else if (PortStatusChange.SuspendChange)
1960 {
1961 DPRINT1("USBH_ProcessPortStateChange: SuspendChange UNIMPLEMENTED. FIXME\n");
1962 DbgBreakPoint();
1963 }
1964 else if (PortStatusChange.OverCurrentIndicatorChange)
1965 {
1966 DPRINT1("USBH_ProcessPortStateChange: OverCurrentIndicatorChange UNIMPLEMENTED. FIXME\n");
1967 DbgBreakPoint();
1968 }
1969 else if (PortStatusChange.ResetChange)
1970 {
1971 RequestValue = USBHUB_FEATURE_C_PORT_RESET;
1972 PortData->PortStatus = *PortStatus;
1973 USBH_SyncClearPortStatus(HubExtension, Port, RequestValue);
1974 }
1975 }
1976
1977 NTSTATUS
1978 NTAPI
1979 USBH_GetPortStatus(IN PUSBHUB_FDO_EXTENSION HubExtension,
1980 IN PULONG PortStatus)
1981 {
1982 PIRP Irp;
1983 PIO_STACK_LOCATION IoStack;
1984 NTSTATUS Status;
1985 KEVENT Event;
1986 IO_STATUS_BLOCK IoStatusBlock;
1987
1988 DPRINT("USBH_GetPortStatus ... \n");
1989
1990 *PortStatus = 0;
1991
1992 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1993
1994 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PORT_STATUS,
1995 HubExtension->LowerDevice,
1996 NULL,
1997 0,
1998 NULL,
1999 0,
2000 TRUE,
2001 &Event,
2002 &IoStatusBlock);
2003
2004 if (!Irp)
2005 {
2006 return STATUS_INSUFFICIENT_RESOURCES;
2007 }
2008
2009 IoStack = IoGetNextIrpStackLocation(Irp);
2010 IoStack->Parameters.Others.Argument1 = PortStatus;
2011
2012 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2013
2014 if (Status == STATUS_PENDING)
2015 {
2016 KeWaitForSingleObject(&Event,
2017 Suspended,
2018 KernelMode,
2019 FALSE,
2020 NULL);
2021 }
2022 else
2023 {
2024 IoStatusBlock.Status = Status;
2025 }
2026
2027 return IoStatusBlock.Status;
2028 }
2029
2030 NTSTATUS
2031 NTAPI
2032 USBH_EnableParentPort(IN PUSBHUB_FDO_EXTENSION HubExtension)
2033 {
2034 PIRP Irp;
2035 NTSTATUS Status;
2036 KEVENT Event;
2037 IO_STATUS_BLOCK IoStatusBlock;
2038
2039 DPRINT("USBH_EnableParentPort ... \n");
2040
2041 KeInitializeEvent(&Event, NotificationEvent, FALSE);
2042
2043 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_ENABLE_PORT,
2044 HubExtension->LowerDevice,
2045 NULL,
2046 0,
2047 NULL,
2048 0,
2049 TRUE,
2050 &Event,
2051 &IoStatusBlock);
2052
2053 if (!Irp)
2054 {
2055 return STATUS_INSUFFICIENT_RESOURCES;
2056 }
2057
2058 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2059
2060 if (Status == STATUS_PENDING)
2061 {
2062 KeWaitForSingleObject(&Event,
2063 Suspended,
2064 KernelMode,
2065 FALSE,
2066 NULL);
2067 }
2068 else
2069 {
2070 IoStatusBlock.Status = Status;
2071 }
2072
2073 return IoStatusBlock.Status;
2074 }
2075
2076 NTSTATUS
2077 NTAPI
2078 USBH_ResetInterruptPipe(IN PUSBHUB_FDO_EXTENSION HubExtension)
2079 {
2080 struct _URB_PIPE_REQUEST * Urb;
2081 NTSTATUS Status;
2082
2083 DPRINT("USBH_ResetInterruptPipe ... \n");
2084
2085 Urb = ExAllocatePoolWithTag(NonPagedPool,
2086 sizeof(struct _URB_PIPE_REQUEST),
2087 USB_HUB_TAG);
2088
2089 if (Urb)
2090 {
2091 RtlZeroMemory(Urb, sizeof(struct _URB_PIPE_REQUEST));
2092
2093 Urb->Hdr.Length = sizeof(struct _URB_PIPE_REQUEST);
2094 Urb->Hdr.Function = URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL;
2095 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2096
2097 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice,
2098 (PURB)Urb);
2099
2100 ExFreePoolWithTag(Urb, USB_HUB_TAG);
2101 }
2102 else
2103 {
2104 Status = STATUS_INSUFFICIENT_RESOURCES;
2105 }
2106
2107 if (NT_SUCCESS(Status))
2108 {
2109 HubExtension->RequestErrors = 0;
2110 }
2111
2112 return Status;
2113 }
2114
2115 NTSTATUS
2116 NTAPI
2117 USBH_ResetHub(IN PUSBHUB_FDO_EXTENSION HubExtension)
2118 {
2119 NTSTATUS Status;
2120 ULONG PortStatusFlags = 0;
2121
2122 DPRINT("USBH_ResetHub: ... \n");
2123
2124 Status = USBH_GetPortStatus(HubExtension, &PortStatusFlags);
2125
2126 if (!NT_SUCCESS(Status))
2127 {
2128 return Status;
2129 }
2130
2131 if (!(PortStatusFlags & USBD_PORT_ENABLED))
2132 {
2133 if (PortStatusFlags & USBD_PORT_CONNECTED)
2134 {
2135 USBH_EnableParentPort(HubExtension);
2136 }
2137 }
2138
2139 Status = USBH_ResetInterruptPipe(HubExtension);
2140
2141 return Status;
2142 }
2143
2144 VOID
2145 NTAPI
2146 USBH_ChangeIndicationWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
2147 IN PVOID Context)
2148 {
2149 PUSBHUB_FDO_EXTENSION LowerHubExtension;
2150 PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension;
2151 PUSBHUB_STATUS_CHANGE_CONTEXT WorkItem;
2152 USB_PORT_STATUS_AND_CHANGE PortStatus;
2153 USB_HUB_STATUS_AND_CHANGE HubStatus;
2154 NTSTATUS Status;
2155 USHORT Port = 0;
2156
2157 DPRINT_SCE("USBH_ChangeIndicationWorker ... \n");
2158
2159 WorkItem = Context;
2160
2161 KeWaitForSingleObject(&HubExtension->HubSemaphore,
2162 Executive,
2163 KernelMode,
2164 FALSE,
2165 NULL);
2166
2167 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING)
2168 {
2169 KeSetEvent(&HubExtension->StatusChangeEvent,
2170 EVENT_INCREMENT,
2171 FALSE);
2172
2173 goto Exit;
2174 }
2175
2176 if (!HubExtension->RequestErrors)
2177 {
2178 goto Enum;
2179 }
2180
2181 DPRINT_SCE("USBH_ChangeIndicationWorker: RequestErrors - %x\n",
2182 HubExtension->RequestErrors);
2183
2184 if (HubExtension->LowerPDO == HubExtension->RootHubPdo)
2185 {
2186 goto Enum;
2187 }
2188
2189 LowerPortExtension = HubExtension->LowerPDO->DeviceExtension;
2190
2191 if (LowerPortExtension->PortPdoFlags & USBHUB_PDO_FLAG_POWER_D1_OR_D2)
2192 {
2193 goto Enum;
2194 }
2195
2196 LowerHubExtension = LowerPortExtension->HubExtension;
2197
2198 if (!LowerHubExtension)
2199 {
2200 goto Enum;
2201 }
2202
2203 Status = USBH_SyncGetPortStatus(LowerHubExtension,
2204 LowerPortExtension->PortNumber,
2205 &PortStatus,
2206 sizeof(USB_PORT_STATUS_AND_CHANGE));
2207
2208 if (!NT_SUCCESS(Status) ||
2209 !PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus)
2210 {
2211 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_REMOVED;
2212
2213 KeSetEvent(&HubExtension->StatusChangeEvent,
2214 EVENT_INCREMENT,
2215 FALSE);
2216
2217 goto Exit;
2218 }
2219
2220 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING))
2221 {
2222 HubExtension->HubFlags |= USBHUB_FDO_FLAG_ESD_RECOVERING;
2223
2224 DPRINT1("USBH_ChangeIndicationWorker: USBHUB_FDO_FLAG_ESD_RECOVERING FIXME\n");
2225 DbgBreakPoint();
2226
2227 goto Exit;
2228 }
2229
2230 Enum:
2231
2232 if (WorkItem->IsRequestErrors)
2233 {
2234 USBH_ResetHub(HubExtension);
2235 }
2236 else
2237 {
2238 for (Port = 0;
2239 Port < HubExtension->HubDescriptor->bNumberOfPorts;
2240 Port++)
2241 {
2242 if (IsBitSet((PUCHAR)(WorkItem + 1), Port))
2243 {
2244 break;
2245 }
2246 }
2247
2248 if (Port)
2249 {
2250 Status = USBH_SyncGetPortStatus(HubExtension,
2251 Port,
2252 &PortStatus,
2253 sizeof(PortStatus));
2254 }
2255 else
2256 {
2257 Status = USBH_SyncGetHubStatus(HubExtension,
2258 &HubStatus,
2259 sizeof(HubStatus));
2260 }
2261
2262 if (NT_SUCCESS(Status))
2263 {
2264 if (Port)
2265 {
2266 USBH_ProcessPortStateChange(HubExtension,
2267 Port,
2268 &PortStatus);
2269 }
2270 else
2271 {
2272 USBH_ProcessHubStateChange(HubExtension,
2273 &HubStatus);
2274 }
2275 }
2276 else
2277 {
2278 HubExtension->RequestErrors++;
2279
2280 if (HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS)
2281 {
2282 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
2283 goto Exit;
2284 }
2285 }
2286 }
2287
2288 USBH_SubmitStatusChangeTransfer(HubExtension);
2289
2290 Exit:
2291
2292 KeReleaseSemaphore(&HubExtension->HubSemaphore,
2293 LOW_REALTIME_PRIORITY,
2294 1,
2295 FALSE);
2296
2297 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2298 {
2299 KeSetEvent(&HubExtension->PendingRequestEvent,
2300 EVENT_INCREMENT,
2301 FALSE);
2302 }
2303
2304 if (!InterlockedDecrement((PLONG)&HubExtension->ResetRequestCount))
2305 {
2306 KeSetEvent(&HubExtension->ResetEvent,
2307 EVENT_INCREMENT,
2308 FALSE);
2309
2310 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEFER_CHECK_IDLE)
2311 {
2312 USBH_CheckHubIdle(HubExtension);
2313 }
2314 }
2315 }
2316
2317 NTSTATUS
2318 NTAPI
2319 USBH_ChangeIndication(IN PDEVICE_OBJECT DeviceObject,
2320 IN PIRP Irp,
2321 IN PVOID Context)
2322 {
2323 PUSBHUB_FDO_EXTENSION HubExtension;
2324 USBD_STATUS UrbStatus;
2325 BOOLEAN IsErrors = FALSE;
2326 PUSBHUB_IO_WORK_ITEM HubWorkItem;
2327 PUSBHUB_STATUS_CHANGE_CONTEXT HubWorkItemBuffer;
2328 USHORT NumPorts;
2329 USHORT Port;
2330 NTSTATUS Status;
2331 PVOID Bitmap;
2332 ULONG BufferLength;
2333
2334 HubExtension = Context;
2335 UrbStatus = HubExtension->SCEWorkerUrb.Hdr.Status;
2336
2337 DPRINT_SCE("USBH_ChangeIndication: IrpStatus - %x, UrbStatus - %x, HubFlags - %lX\n",
2338 Irp->IoStatus.Status,
2339 UrbStatus,
2340 HubExtension->HubFlags);
2341
2342 if (NT_ERROR(Irp->IoStatus.Status) || USBD_ERROR(UrbStatus) ||
2343 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED) ||
2344 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING))
2345 {
2346 HubExtension->RequestErrors++;
2347
2348 IsErrors = TRUE;
2349
2350 KeSetEvent(&HubExtension->StatusChangeEvent,
2351 EVENT_INCREMENT,
2352 FALSE);
2353
2354 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
2355 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED ||
2356 HubExtension->RequestErrors > USBHUB_MAX_REQUEST_ERRORS ||
2357 Irp->IoStatus.Status == STATUS_DELETE_PENDING)
2358 {
2359 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2360 HubExtension->RequestErrors);
2361
2362 return STATUS_MORE_PROCESSING_REQUIRED;
2363 }
2364
2365 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2366 HubExtension->RequestErrors);
2367 }
2368 else
2369 {
2370 HubExtension->RequestErrors = 0;
2371 }
2372
2373 BufferLength = sizeof(USBHUB_STATUS_CHANGE_CONTEXT) +
2374 HubExtension->SCEBitmapLength;
2375
2376 Status = USBH_AllocateWorkItem(HubExtension,
2377 &HubWorkItem,
2378 USBH_ChangeIndicationWorker,
2379 BufferLength,
2380 (PVOID *)&HubWorkItemBuffer,
2381 DelayedWorkQueue);
2382
2383 if (!NT_SUCCESS(Status))
2384 {
2385 return STATUS_MORE_PROCESSING_REQUIRED;
2386 }
2387
2388 RtlZeroMemory(HubWorkItemBuffer, BufferLength);
2389
2390 HubWorkItemBuffer->IsRequestErrors = FALSE;
2391
2392 if (IsErrors)
2393 {
2394 HubWorkItemBuffer->IsRequestErrors = TRUE;
2395 }
2396
2397 if (InterlockedIncrement(&HubExtension->ResetRequestCount) == 1)
2398 {
2399 KeClearEvent(&HubExtension->ResetEvent);
2400 }
2401
2402 HubWorkItemBuffer->HubExtension = HubExtension;
2403
2404 HubExtension->WorkItemToQueue = HubWorkItem;
2405
2406 Bitmap = HubWorkItemBuffer + 1;
2407
2408 RtlCopyMemory(Bitmap,
2409 HubExtension->SCEBitmap,
2410 HubExtension->SCEBitmapLength);
2411
2412 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
2413
2414 for (Port = 0; Port <= NumPorts; ++Port)
2415 {
2416 if (IsBitSet(Bitmap, Port))
2417 {
2418 break;
2419 }
2420 }
2421
2422 if (Port > NumPorts)
2423 {
2424 Port = 0;
2425 }
2426
2427 Status = USBH_ChangeIndicationQueryChange(HubExtension,
2428 HubExtension->ResetPortIrp,
2429 &HubExtension->SCEWorkerUrb,
2430 Port);
2431
2432 if (NT_ERROR(Status))
2433 {
2434 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEVICE_FAILED;
2435 }
2436
2437 return STATUS_MORE_PROCESSING_REQUIRED;
2438 }
2439
2440 NTSTATUS
2441 NTAPI
2442 USBH_SubmitStatusChangeTransfer(IN PUSBHUB_FDO_EXTENSION HubExtension)
2443 {
2444 PIRP Irp;
2445 NTSTATUS Status;
2446 struct _URB_BULK_OR_INTERRUPT_TRANSFER * Urb;
2447 PIO_STACK_LOCATION IoStack;
2448
2449 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubExtension - %p, SCEIrp - %p\n",
2450 HubExtension,
2451 HubExtension->SCEIrp);
2452
2453 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_NOT_D0_STATE)
2454 {
2455 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: USBHUB_FDO_FLAG_NOT_D0_STATE\n");
2456 DPRINT_SCE("USBH_SubmitStatusChangeTransfer: HubFlags - %lX\n",
2457 HubExtension->HubFlags);
2458
2459 return STATUS_INVALID_DEVICE_STATE;
2460 }
2461
2462 Irp = HubExtension->SCEIrp;
2463
2464 if (!Irp)
2465 {
2466 return STATUS_INVALID_DEVICE_STATE;
2467 }
2468
2469 Urb = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *)&HubExtension->SCEWorkerUrb;
2470
2471 Urb->Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
2472 Urb->Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
2473 Urb->Hdr.UsbdDeviceHandle = NULL;
2474
2475 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2476 Urb->TransferFlags = USBD_SHORT_TRANSFER_OK;
2477 Urb->TransferBuffer = HubExtension->SCEBitmap;
2478 Urb->TransferBufferLength = HubExtension->SCEBitmapLength;
2479 Urb->TransferBufferMDL = NULL;
2480 Urb->UrbLink = NULL;
2481
2482 IoInitializeIrp(Irp,
2483 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
2484 HubExtension->LowerDevice->StackSize);
2485
2486 IoStack = IoGetNextIrpStackLocation(Irp);
2487
2488 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
2489 IoStack->Parameters.Others.Argument1 = &HubExtension->SCEWorkerUrb;
2490 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
2491
2492 IoSetCompletionRoutine(Irp,
2493 USBH_ChangeIndication,
2494 HubExtension,
2495 TRUE,
2496 TRUE,
2497 TRUE);
2498
2499 KeClearEvent(&HubExtension->StatusChangeEvent);
2500
2501 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2502
2503 return Status;
2504 }
2505
2506 NTSTATUS
2507 NTAPI
2508 USBD_CreateDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2509 IN PUSB_DEVICE_HANDLE * OutDeviceHandle,
2510 IN USB_PORT_STATUS UsbPortStatus,
2511 IN USHORT Port)
2512 {
2513 PUSB_DEVICE_HANDLE HubDeviceHandle;
2514 PUSB_BUSIFFN_CREATE_USB_DEVICE CreateUsbDevice;
2515
2516 DPRINT("USBD_CreateDeviceEx: Port - %x, UsbPortStatus - 0x%04X\n",
2517 Port,
2518 UsbPortStatus.AsUshort16);
2519
2520 CreateUsbDevice = HubExtension->BusInterface.CreateUsbDevice;
2521
2522 if (!CreateUsbDevice)
2523 {
2524 return STATUS_NOT_IMPLEMENTED;
2525 }
2526
2527 HubDeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
2528
2529 return CreateUsbDevice(HubExtension->BusInterface.BusContext,
2530 OutDeviceHandle,
2531 HubDeviceHandle,
2532 UsbPortStatus.AsUshort16,
2533 Port);
2534 }
2535
2536 NTSTATUS
2537 NTAPI
2538 USBD_RemoveDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2539 IN PUSB_DEVICE_HANDLE DeviceHandle,
2540 IN ULONG Flags)
2541 {
2542 PUSB_BUSIFFN_REMOVE_USB_DEVICE RemoveUsbDevice;
2543
2544 DPRINT("USBD_RemoveDeviceEx: DeviceHandle - %p, Flags - %X\n",
2545 DeviceHandle,
2546 Flags);
2547
2548 RemoveUsbDevice = HubExtension->BusInterface.RemoveUsbDevice;
2549
2550 if (!RemoveUsbDevice)
2551 {
2552 return STATUS_NOT_IMPLEMENTED;
2553 }
2554
2555 return RemoveUsbDevice(HubExtension->BusInterface.BusContext,
2556 DeviceHandle,
2557 Flags);
2558 }
2559
2560 NTSTATUS
2561 NTAPI
2562 USBD_InitializeDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2563 IN PUSB_DEVICE_HANDLE DeviceHandle,
2564 IN PUCHAR DeviceDescriptorBuffer,
2565 IN ULONG DeviceDescriptorBufferLength,
2566 IN PUCHAR ConfigDescriptorBuffer,
2567 IN ULONG ConfigDescriptorBufferLength)
2568 {
2569 NTSTATUS Status;
2570 PUSB_BUSIFFN_INITIALIZE_USB_DEVICE InitializeUsbDevice;
2571 PUSB_BUSIFFN_GET_USB_DESCRIPTORS GetUsbDescriptors;
2572
2573 DPRINT("USBD_InitializeDeviceEx: ... \n");
2574
2575 InitializeUsbDevice = HubExtension->BusInterface.InitializeUsbDevice;
2576 GetUsbDescriptors = HubExtension->BusInterface.GetUsbDescriptors;
2577
2578 if (!InitializeUsbDevice || !GetUsbDescriptors)
2579 {
2580 return STATUS_NOT_IMPLEMENTED;
2581 }
2582
2583 Status = InitializeUsbDevice(HubExtension->BusInterface.BusContext,
2584 DeviceHandle);
2585
2586 if (!NT_SUCCESS(Status))
2587 {
2588 return Status;
2589 }
2590
2591 return GetUsbDescriptors(HubExtension->BusInterface.BusContext,
2592 DeviceHandle,
2593 DeviceDescriptorBuffer,
2594 &DeviceDescriptorBufferLength,
2595 ConfigDescriptorBuffer,
2596 &ConfigDescriptorBufferLength);
2597 }
2598
2599 VOID
2600 NTAPI
2601 USBHUB_SetDeviceHandleData(IN PUSBHUB_FDO_EXTENSION HubExtension,
2602 IN PDEVICE_OBJECT UsbDevicePdo,
2603 IN PVOID DeviceHandle)
2604 {
2605 PUSB_BUSIFFN_SET_DEVHANDLE_DATA SetDeviceHandleData;
2606
2607 DPRINT("USBHUB_SetDeviceHandleData ... \n");
2608
2609 SetDeviceHandleData = HubExtension->BusInterface.SetDeviceHandleData;
2610
2611 if (!SetDeviceHandleData)
2612 {
2613 return;
2614 }
2615
2616 SetDeviceHandleData(HubExtension->BusInterface.BusContext,
2617 DeviceHandle,
2618 UsbDevicePdo);
2619 }
2620
2621 VOID
2622 NTAPI
2623 USBHUB_FlushAllTransfers(IN PUSBHUB_FDO_EXTENSION HubExtension)
2624 {
2625 PUSB_BUSIFFN_FLUSH_TRANSFERS FlushTransfers;
2626
2627 DPRINT("USBHUB_FlushAllTransfers ... \n");
2628
2629 FlushTransfers = HubExtension->BusInterface.FlushTransfers;
2630
2631 if (FlushTransfers)
2632 {
2633 FlushTransfers(HubExtension->BusInterface.BusContext, NULL);
2634 }
2635 }
2636
2637 NTSTATUS
2638 NTAPI
2639 USBD_GetDeviceInformationEx(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
2640 IN PUSBHUB_FDO_EXTENSION HubExtension,
2641 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info,
2642 IN ULONG Length,
2643 IN PUSB_DEVICE_HANDLE DeviceHandle)
2644 {
2645 PUSB_BUSIFFN_GET_DEVICE_INFORMATION QueryDeviceInformation;
2646 PUSB_DEVICE_INFORMATION_0 DeviceInfo;
2647 SIZE_T DeviceInfoLength;
2648 PUSB_NODE_CONNECTION_INFORMATION_EX NodeInfo;
2649 SIZE_T NodeInfoLength;
2650 ULONG PipeNumber;
2651 ULONG dummy;
2652 NTSTATUS Status;
2653
2654 DPRINT("USBD_GetDeviceInformationEx ... \n");
2655
2656 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
2657
2658 if (!QueryDeviceInformation)
2659 {
2660 Status = STATUS_NOT_IMPLEMENTED;
2661 return Status;
2662 }
2663
2664 DeviceInfoLength = sizeof(USB_DEVICE_INFORMATION_0);
2665
2666 while (TRUE)
2667 {
2668 DeviceInfo = ExAllocatePoolWithTag(PagedPool,
2669 DeviceInfoLength,
2670 USB_HUB_TAG);
2671
2672 if (!DeviceInfo)
2673 {
2674 return STATUS_INSUFFICIENT_RESOURCES;
2675 }
2676
2677 RtlZeroMemory(DeviceInfo, DeviceInfoLength);
2678
2679 DeviceInfo->InformationLevel = 0;
2680
2681 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
2682 DeviceHandle,
2683 DeviceInfo,
2684 DeviceInfoLength,
2685 &dummy);
2686
2687 if (Status != STATUS_BUFFER_TOO_SMALL)
2688 {
2689 break;
2690 }
2691
2692 DeviceInfoLength = DeviceInfo->ActualLength;
2693
2694 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2695 }
2696
2697 NodeInfo = NULL;
2698 NodeInfoLength = 0;
2699
2700 if (NT_SUCCESS(Status))
2701 {
2702 NodeInfoLength = (sizeof(USB_NODE_CONNECTION_INFORMATION_EX) - sizeof(USB_PIPE_INFO)) +
2703 DeviceInfo->NumberOfOpenPipes * sizeof(USB_PIPE_INFO);
2704
2705 NodeInfo = ExAllocatePoolWithTag(PagedPool, NodeInfoLength, USB_HUB_TAG);
2706
2707 if (!NodeInfo)
2708 {
2709 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2710 return STATUS_INSUFFICIENT_RESOURCES;
2711 }
2712
2713 RtlZeroMemory(NodeInfo, NodeInfoLength);
2714
2715 NodeInfo->ConnectionIndex = Info->ConnectionIndex;
2716
2717 RtlCopyMemory(&NodeInfo->DeviceDescriptor,
2718 &DeviceInfo->DeviceDescriptor,
2719 sizeof(USB_DEVICE_DESCRIPTOR));
2720
2721 NodeInfo->CurrentConfigurationValue = DeviceInfo->CurrentConfigurationValue;
2722 NodeInfo->Speed = DeviceInfo->DeviceSpeed;
2723 NodeInfo->DeviceIsHub = PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_HUB_DEVICE;
2724 NodeInfo->DeviceAddress = DeviceInfo->DeviceAddress;
2725 NodeInfo->NumberOfOpenPipes = DeviceInfo->NumberOfOpenPipes;
2726 NodeInfo->ConnectionStatus = Info->ConnectionStatus;
2727
2728 for (PipeNumber = 0;
2729 PipeNumber < DeviceInfo->NumberOfOpenPipes;
2730 PipeNumber++)
2731 {
2732 RtlCopyMemory(&NodeInfo->PipeList[PipeNumber],
2733 &DeviceInfo->PipeList[PipeNumber],
2734 sizeof(USB_PIPE_INFO));
2735 }
2736 }
2737
2738 ExFreePoolWithTag(DeviceInfo, USB_HUB_TAG);
2739
2740 if (NodeInfo)
2741 {
2742 if (NodeInfoLength <= Length)
2743 {
2744 Length = NodeInfoLength;
2745 }
2746 else
2747 {
2748 Status = STATUS_BUFFER_TOO_SMALL;
2749 }
2750
2751 RtlCopyMemory(Info, NodeInfo, Length);
2752
2753 ExFreePoolWithTag(NodeInfo, USB_HUB_TAG);
2754 }
2755
2756 return Status;
2757 }
2758
2759 NTSTATUS
2760 NTAPI
2761 USBD_RestoreDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension,
2762 IN OUT PUSB_DEVICE_HANDLE OldDeviceHandle,
2763 IN OUT PUSB_DEVICE_HANDLE NewDeviceHandle)
2764 {
2765 PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice;
2766 NTSTATUS Status;
2767
2768 DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n",
2769 HubExtension,
2770 OldDeviceHandle,
2771 NewDeviceHandle);
2772
2773 RestoreUsbDevice = HubExtension->BusInterface.RestoreUsbDevice;
2774
2775 if (RestoreUsbDevice)
2776 {
2777 Status = RestoreUsbDevice(HubExtension->BusInterface.BusContext,
2778 OldDeviceHandle,
2779 NewDeviceHandle);
2780 }
2781 else
2782 {
2783 Status = STATUS_NOT_IMPLEMENTED;
2784 }
2785
2786 return Status;
2787 }
2788
2789 NTSTATUS
2790 NTAPI
2791 USBH_AllocateWorkItem(PUSBHUB_FDO_EXTENSION HubExtension,
2792 PUSBHUB_IO_WORK_ITEM * OutHubIoWorkItem,
2793 PUSBHUB_WORKER_ROUTINE WorkerRoutine,
2794 SIZE_T BufferLength,
2795 PVOID * OutHubWorkItemBuffer,
2796 WORK_QUEUE_TYPE Type)
2797 {
2798 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2799 PIO_WORKITEM WorkItem;
2800 PVOID WorkItemBuffer;
2801
2802 DPRINT("USBH_AllocateWorkItem: ... \n");
2803
2804 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_WITEM_INIT))
2805 {
2806 return STATUS_INVALID_PARAMETER;
2807 }
2808
2809 HubIoWorkItem = ExAllocatePoolWithTag(NonPagedPool,
2810 sizeof(USBHUB_IO_WORK_ITEM),
2811 USB_HUB_TAG);
2812
2813 if (!HubIoWorkItem)
2814 {
2815 return STATUS_INSUFFICIENT_RESOURCES;
2816 }
2817
2818 RtlZeroMemory(HubIoWorkItem, sizeof(USBHUB_IO_WORK_ITEM));
2819
2820 WorkItem = IoAllocateWorkItem(HubExtension->Common.SelfDevice);
2821
2822 HubIoWorkItem->HubWorkItem = WorkItem;
2823
2824 if (!WorkItem)
2825 {
2826 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2827 return STATUS_INSUFFICIENT_RESOURCES;
2828 }
2829
2830 if (BufferLength && OutHubWorkItemBuffer)
2831 {
2832 WorkItemBuffer = ExAllocatePoolWithTag(NonPagedPool,
2833 BufferLength,
2834 USB_HUB_TAG);
2835
2836 HubIoWorkItem->HubWorkItemBuffer = WorkItemBuffer;
2837
2838 if (!WorkItemBuffer)
2839 {
2840 IoFreeWorkItem(HubIoWorkItem->HubWorkItem);
2841 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2842
2843 return STATUS_INSUFFICIENT_RESOURCES;
2844 }
2845
2846 RtlZeroMemory(WorkItemBuffer, BufferLength);
2847 }
2848 else
2849 {
2850 HubIoWorkItem->HubWorkItemBuffer = NULL;
2851 }
2852
2853 HubIoWorkItem->HubWorkItemType = Type;
2854 HubIoWorkItem->HubExtension = HubExtension;
2855 HubIoWorkItem->HubWorkerRoutine = WorkerRoutine;
2856
2857 if (OutHubIoWorkItem)
2858 {
2859 *OutHubIoWorkItem = HubIoWorkItem;
2860 }
2861
2862 if (OutHubWorkItemBuffer)
2863 {
2864 *OutHubWorkItemBuffer = HubIoWorkItem->HubWorkItemBuffer;
2865 }
2866
2867 return STATUS_SUCCESS;
2868 }
2869
2870 VOID
2871 NTAPI
2872 USBH_Worker(IN PDEVICE_OBJECT DeviceObject,
2873 IN PVOID Context)
2874 {
2875 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2876 PUSBHUB_FDO_EXTENSION HubExtension;
2877 KIRQL OldIrql;
2878 PIO_WORKITEM WorkItem;
2879
2880 DPRINT("USBH_Worker: HubIoWorkItem - %p\n", Context);
2881
2882 HubIoWorkItem = Context;
2883
2884 InterlockedDecrement(&HubIoWorkItem->HubWorkerQueued);
2885
2886 HubExtension = HubIoWorkItem->HubExtension;
2887 WorkItem = HubIoWorkItem->HubWorkItem;
2888
2889 HubIoWorkItem->HubWorkerRoutine(HubIoWorkItem->HubExtension,
2890 HubIoWorkItem->HubWorkItemBuffer);
2891
2892 KeAcquireSpinLock(&HubExtension->WorkItemSpinLock, &OldIrql);
2893 RemoveEntryList(&HubIoWorkItem->HubWorkItemLink);
2894 KeReleaseSpinLock(&HubExtension->WorkItemSpinLock, OldIrql);
2895
2896 if (HubIoWorkItem->HubWorkItemBuffer)
2897 {
2898 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG);
2899 }
2900
2901 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2902
2903 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2904 {
2905 KeSetEvent(&HubExtension->PendingRequestEvent,
2906 EVENT_INCREMENT,
2907 FALSE);
2908 }
2909
2910 IoFreeWorkItem(WorkItem);
2911
2912 DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context);
2913 }
2914
2915 VOID
2916 NTAPI
2917 USBH_QueueWorkItem(IN PUSBHUB_FDO_EXTENSION HubExtension,
2918 IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem)
2919 {
2920 DPRINT("USBH_QueueWorkItem: ... \n");
2921
2922 InterlockedIncrement(&HubExtension->PendingRequestCount);
2923 InterlockedIncrement(&HubIoWorkItem->HubWorkerQueued);
2924
2925 ExInterlockedInsertTailList(&HubExtension->WorkItemList,
2926 &HubIoWorkItem->HubWorkItemLink,
2927 &HubExtension->WorkItemSpinLock);
2928
2929 IoQueueWorkItem(HubIoWorkItem->HubWorkItem,
2930 USBH_Worker,
2931 HubIoWorkItem->HubWorkItemType,
2932 HubIoWorkItem);
2933 }
2934
2935 VOID
2936 NTAPI
2937 USBH_FreeWorkItem(IN PUSBHUB_IO_WORK_ITEM HubIoWorkItem)
2938 {
2939 PIO_WORKITEM WorkItem;
2940
2941 DPRINT("USBH_FreeWorkItem: ... \n");
2942
2943 WorkItem = HubIoWorkItem->HubWorkItem;
2944
2945 if (HubIoWorkItem->HubWorkItemBuffer)
2946 {
2947 ExFreePoolWithTag(HubIoWorkItem->HubWorkItemBuffer, USB_HUB_TAG);
2948 }
2949
2950 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2951
2952 IoFreeWorkItem(WorkItem);
2953 }
2954
2955 VOID
2956 NTAPI
2957 USBHUB_RootHubCallBack(IN PVOID Context)
2958 {
2959 PUSBHUB_FDO_EXTENSION HubExtension;
2960
2961 DPRINT("USBHUB_RootHubCallBack: ... \n");
2962
2963 HubExtension = Context;
2964
2965 if (HubExtension->SCEIrp)
2966 {
2967 HubExtension->HubFlags |= (USBHUB_FDO_FLAG_DO_ENUMERATION |
2968 USBHUB_FDO_FLAG_NOT_ENUMERATED);
2969
2970 USBH_SubmitStatusChangeTransfer(HubExtension);
2971
2972 IoInvalidateDeviceRelations(HubExtension->LowerPDO, BusRelations);
2973 }
2974 else
2975 {
2976 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION;
2977 }
2978
2979 KeSetEvent(&HubExtension->RootHubNotificationEvent,
2980 EVENT_INCREMENT,
2981 FALSE);
2982 }
2983
2984 NTSTATUS
2985 NTAPI
2986 USBD_RegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension)
2987 {
2988 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification;
2989
2990 DPRINT("USBD_RegisterRootHubCallBack: ... \n");
2991
2992 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification;
2993
2994 if (!RootHubInitNotification)
2995 {
2996 return STATUS_NOT_IMPLEMENTED;
2997 }
2998
2999 KeClearEvent(&HubExtension->RootHubNotificationEvent);
3000
3001 return RootHubInitNotification(HubExtension->BusInterface.BusContext,
3002 HubExtension,
3003 USBHUB_RootHubCallBack);
3004 }
3005
3006 NTSTATUS
3007 NTAPI
3008 USBD_UnRegisterRootHubCallBack(IN PUSBHUB_FDO_EXTENSION HubExtension)
3009 {
3010 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification;
3011 NTSTATUS Status;
3012
3013 DPRINT("USBD_UnRegisterRootHubCallBack ... \n");
3014
3015 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification;
3016
3017 if (!RootHubInitNotification)
3018 {
3019 return STATUS_NOT_IMPLEMENTED;
3020 }
3021
3022 Status = RootHubInitNotification(HubExtension->BusInterface.BusContext,
3023 NULL,
3024 NULL);
3025
3026 if (!NT_SUCCESS(Status))
3027 {
3028 KeWaitForSingleObject(&HubExtension->RootHubNotificationEvent,
3029 Executive,
3030 KernelMode,
3031 FALSE,
3032 NULL);
3033 }
3034
3035 return Status;
3036 }
3037
3038 VOID
3039 NTAPI
3040 USBH_HubSetDWakeCompletion(IN PDEVICE_OBJECT DeviceObject,
3041 IN UCHAR MinorFunction,
3042 IN POWER_STATE PowerState,
3043 IN PVOID Context,
3044 IN PIO_STATUS_BLOCK IoStatus)
3045 {
3046 DPRINT("USBH_HubSetDWakeCompletion: ... \n");
3047 KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
3048 }
3049
3050 VOID
3051 NTAPI
3052 USBH_HubQueuePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
3053 IN PLIST_ENTRY IdleList)
3054 {
3055 PDEVICE_OBJECT PortDevice;
3056 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3057 PIRP IdleIrp;
3058 PIRP HubIdleIrp;
3059 ULONG NumPorts;
3060 ULONG Port;
3061 KIRQL Irql;
3062
3063 DPRINT("USBH_HubQueuePortIdleIrps ... \n");
3064
3065 InitializeListHead(IdleList);
3066
3067 IoAcquireCancelSpinLock(&Irql);
3068
3069 NumPorts = HubExtension->HubDescriptor->bNumberOfPorts;
3070
3071 for (Port = 0; Port < NumPorts; ++Port)
3072 {
3073 PortDevice = HubExtension->PortData[Port].DeviceObject;
3074
3075 if (PortDevice)
3076 {
3077 PortExtension = PortDevice->DeviceExtension;
3078
3079 IdleIrp = PortExtension->IdleNotificationIrp;
3080 PortExtension->IdleNotificationIrp = NULL;
3081
3082 if (IdleIrp && IoSetCancelRoutine(IdleIrp, NULL))
3083 {
3084 DPRINT1("USBH_HubQueuePortIdleIrps: IdleIrp != NULL. FIXME\n");
3085 DbgBreakPoint();
3086 }
3087 }
3088 }
3089
3090 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
3091 {
3092 HubIdleIrp = HubExtension->PendingIdleIrp;
3093 HubExtension->PendingIdleIrp = NULL;
3094 }
3095 else
3096 {
3097 HubIdleIrp = NULL;
3098 }
3099
3100 IoReleaseCancelSpinLock(Irql);
3101
3102 if (HubIdleIrp)
3103 {
3104 USBH_HubCancelIdleIrp(HubExtension, HubIdleIrp);
3105 }
3106 }
3107
3108 VOID
3109 NTAPI
3110 USBH_HubCompleteQueuedPortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
3111 IN PLIST_ENTRY IdleList,
3112 IN NTSTATUS NtStatus)
3113 {
3114 DPRINT("USBH_HubCompleteQueuedPortIdleIrps ... \n");
3115
3116 while (!IsListEmpty(IdleList))
3117 {
3118 DPRINT1("USBH_HubCompleteQueuedPortIdleIrps: IdleList not Empty. FIXME\n");
3119 DbgBreakPoint();
3120 }
3121 }
3122
3123 VOID
3124 NTAPI
3125 USBH_FlushPortPwrList(IN PUSBHUB_FDO_EXTENSION HubExtension)
3126 {
3127 PDEVICE_OBJECT PortDevice;
3128 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3129 PLIST_ENTRY Entry;
3130 ULONG Port;
3131
3132 DPRINT("USBH_FlushPortPwrList ... \n");
3133
3134 InterlockedIncrement((PLONG)&HubExtension->PendingRequestCount);
3135
3136 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3137 Executive,
3138 KernelMode,
3139 FALSE,
3140 NULL);
3141
3142 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; ++Port)
3143 {
3144 PortDevice = HubExtension->PortData[Port].DeviceObject;
3145
3146 if (!PortDevice)
3147 {
3148 continue;
3149 }
3150
3151 PortExtension = PortDevice->DeviceExtension;
3152
3153 InterlockedExchange((PLONG)&PortExtension->StateBehindD2, 0);
3154
3155 while (TRUE)
3156 {
3157 Entry = ExInterlockedRemoveHeadList(&PortExtension->PortPowerList,
3158 &PortExtension->PortPowerListSpinLock);
3159
3160 if (!Entry)
3161 {
3162 break;
3163 }
3164
3165 DPRINT1("USBH_FlushPortPwrList: PortPowerList FIXME\n");
3166 DbgBreakPoint();
3167 }
3168 }
3169
3170 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3171 LOW_REALTIME_PRIORITY,
3172 1,
3173 FALSE);
3174
3175 if (!InterlockedDecrement((PLONG)&HubExtension->PendingRequestCount))
3176 {
3177 KeSetEvent(&HubExtension->PendingRequestEvent,
3178 EVENT_INCREMENT,
3179 FALSE);
3180 }
3181 }
3182
3183 VOID
3184 NTAPI
3185 USBH_HubCompletePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension,
3186 IN NTSTATUS NtStatus)
3187 {
3188 LIST_ENTRY IdleList;
3189
3190 DPRINT("USBH_HubCompletePortIdleIrps ... \n");
3191
3192 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)
3193 {
3194 USBH_HubQueuePortIdleIrps(HubExtension, &IdleList);
3195
3196 USBH_HubCompleteQueuedPortIdleIrps(HubExtension,
3197 &IdleList,
3198 NtStatus);
3199
3200 USBH_FlushPortPwrList(HubExtension);
3201 }
3202 }
3203
3204 VOID
3205 NTAPI
3206 USBH_HubCancelIdleIrp(IN PUSBHUB_FDO_EXTENSION HubExtension,
3207 IN PIRP IdleIrp)
3208 {
3209 DPRINT("USBH_HubCancelIdleIrp ... \n");
3210
3211 IoCancelIrp(IdleIrp);
3212
3213 if (InterlockedExchange(&HubExtension->IdleRequestLock, 1))
3214 {
3215 IoFreeIrp(IdleIrp);
3216 }
3217 }
3218
3219 BOOLEAN
3220 NTAPI
3221 USBH_CheckIdleAbort(IN PUSBHUB_FDO_EXTENSION HubExtension,
3222 IN BOOLEAN IsWait,
3223 IN BOOLEAN IsExtCheck)
3224 {
3225 PDEVICE_OBJECT PdoDevice;
3226 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3227 PUSBHUB_PORT_DATA PortData;
3228 ULONG Port;
3229 BOOLEAN Result = FALSE;
3230
3231 DPRINT("USBH_CheckIdleAbort: ... \n");
3232
3233 InterlockedIncrement(&HubExtension->PendingRequestCount);
3234
3235 if (IsWait == TRUE)
3236 {
3237 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3238 Executive,
3239 KernelMode,
3240 FALSE,
3241 NULL);
3242 }
3243
3244 PortData = HubExtension->PortData;
3245
3246 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++)
3247 {
3248 PdoDevice = PortData[Port].DeviceObject;
3249
3250 if (PdoDevice)
3251 {
3252 PortExtension = PdoDevice->DeviceExtension;
3253
3254 if (PortExtension->PoRequestCounter)
3255 {
3256 Result = TRUE;
3257 goto Wait;
3258 }
3259 }
3260 }
3261
3262 if (IsExtCheck == TRUE)
3263 {
3264 PortData = HubExtension->PortData;
3265
3266 for (Port = 0;
3267 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3268 Port++)
3269 {
3270 PdoDevice = PortData[Port].DeviceObject;
3271
3272 if (PdoDevice)
3273 {
3274 PortExtension = PdoDevice->DeviceExtension;
3275 InterlockedExchange(&PortExtension->StateBehindD2, 0);
3276 }
3277 }
3278 }
3279
3280 Wait:
3281
3282 if (IsWait == TRUE)
3283 {
3284 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3285 LOW_REALTIME_PRIORITY,
3286 1,
3287 FALSE);
3288 }
3289
3290 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3291 {
3292 KeSetEvent(&HubExtension->PendingRequestEvent,
3293 EVENT_INCREMENT,
3294 FALSE);
3295 }
3296
3297 return Result;
3298 }
3299
3300 VOID
3301 NTAPI
3302 USBH_FdoWaitWakeIrpCompletion(IN PDEVICE_OBJECT DeviceObject,
3303 IN UCHAR MinorFunction,
3304 IN POWER_STATE PowerState,
3305 IN PVOID Context,
3306 IN PIO_STATUS_BLOCK IoStatus)
3307 {
3308 DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n");
3309 }
3310
3311 NTSTATUS
3312 NTAPI
3313 USBH_FdoSubmitWaitWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
3314 {
3315 POWER_STATE PowerState;
3316 NTSTATUS Status;
3317 PIRP Irp = NULL;
3318 KIRQL Irql;
3319
3320 DPRINT("USBH_FdoSubmitWaitWakeIrp: ... \n");
3321
3322 PowerState.SystemState = HubExtension->SystemWake;
3323 HubExtension->HubFlags |= USBHUB_FDO_FLAG_PENDING_WAKE_IRP;
3324
3325 InterlockedIncrement(&HubExtension->PendingRequestCount);
3326 InterlockedExchange(&HubExtension->FdoWaitWakeLock, 0);
3327
3328 Status = PoRequestPowerIrp(HubExtension->LowerPDO,
3329 IRP_MN_WAIT_WAKE,
3330 PowerState,
3331 USBH_FdoWaitWakeIrpCompletion,
3332 HubExtension,
3333 &Irp);
3334
3335 IoAcquireCancelSpinLock(&Irql);
3336
3337 if (Status == STATUS_PENDING)
3338 {
3339 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP)
3340 {
3341 HubExtension->PendingWakeIrp = Irp;
3342 DPRINT("USBH_FdoSubmitWaitWakeIrp: PendingWakeIrp - %p\n",
3343 HubExtension->PendingWakeIrp);
3344 }
3345 }
3346 else
3347 {
3348 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_PENDING_WAKE_IRP;
3349
3350 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3351 {
3352 KeSetEvent(&HubExtension->PendingRequestEvent,
3353 EVENT_INCREMENT,
3354 FALSE);
3355 }
3356 }
3357
3358 IoReleaseCancelSpinLock(Irql);
3359
3360 return Status;
3361 }
3362
3363 VOID
3364 NTAPI
3365 USBH_FdoIdleNotificationCallback(IN PVOID Context)
3366 {
3367 PUSBHUB_FDO_EXTENSION HubExtension;
3368 PUSBHUB_PORT_DATA PortData;
3369 PDEVICE_OBJECT PortDevice;
3370 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3371 PIRP Irp = NULL;
3372 PIRP IdleIrp;
3373 POWER_STATE PowerState;
3374 KEVENT Event;
3375 ULONG Port;
3376 PIO_STACK_LOCATION IoStack;
3377 PUSB_IDLE_CALLBACK_INFO CallbackInfo;
3378 BOOLEAN IsReady;
3379 KIRQL OldIrql;
3380 NTSTATUS Status;
3381
3382 HubExtension = Context;
3383
3384 DPRINT("USBH_FdoIdleNotificationCallback: HubExtension - %p, HubFlags - %lX\n",
3385 HubExtension,
3386 HubExtension->HubFlags);
3387
3388 if (HubExtension->HubFlags & (USBHUB_FDO_FLAG_ENUM_POST_RECOVER |
3389 USBHUB_FDO_FLAG_WAKEUP_START |
3390 USBHUB_FDO_FLAG_DEVICE_REMOVED |
3391 USBHUB_FDO_FLAG_STATE_CHANGING |
3392 USBHUB_FDO_FLAG_ESD_RECOVERING |
3393 USBHUB_FDO_FLAG_DEVICE_FAILED |
3394 USBHUB_FDO_FLAG_DEVICE_STOPPING))
3395 {
3396 DbgBreakPoint();
3397 return;
3398 }
3399
3400 HubExtension->HubFlags |= USBHUB_FDO_FLAG_GOING_IDLE;
3401
3402 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_PENDING_WAKE_IRP))
3403 {
3404 Status = USBH_FdoSubmitWaitWakeIrp(HubExtension);
3405
3406 if (Status != STATUS_PENDING)
3407 {
3408 DPRINT("Status != STATUS_PENDING. DbgBreakPoint()\n");
3409 DbgBreakPoint();
3410 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE;
3411 return;
3412 }
3413 }
3414
3415 InterlockedIncrement(&HubExtension->PendingRequestCount);
3416
3417 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3418 Executive,
3419 KernelMode,
3420 FALSE,
3421 NULL);
3422
3423 PortData = HubExtension->PortData;
3424 IsReady = TRUE;
3425
3426 for (Port = 0;
3427 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3428 Port++)
3429 {
3430 PortDevice = PortData[Port].DeviceObject;
3431
3432 if (PortDevice)
3433 {
3434 PortExtension = PortDevice->DeviceExtension;
3435
3436 IdleIrp = PortExtension->IdleNotificationIrp;
3437
3438 if (!IdleIrp)
3439 {
3440 IsReady = FALSE;
3441 goto IdleHub;
3442 }
3443
3444 IoStack = IoGetCurrentIrpStackLocation(IdleIrp);
3445
3446 CallbackInfo = IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
3447
3448 if (!CallbackInfo)
3449 {
3450 IsReady = FALSE;
3451 goto IdleHub;
3452 }
3453
3454 if (!CallbackInfo->IdleCallback)
3455 {
3456 IsReady = FALSE;
3457 goto IdleHub;
3458 }
3459
3460 if (PortExtension->PendingSystemPoRequest)
3461 {
3462 IsReady = FALSE;
3463 goto IdleHub;
3464 }
3465
3466 if (InterlockedCompareExchange(&PortExtension->StateBehindD2,
3467 1,
3468 0))
3469 {
3470 IsReady = FALSE;
3471 goto IdleHub;
3472 }
3473
3474 DPRINT("USBH_FdoIdleNotificationCallback: IdleContext - %p\n",
3475 CallbackInfo->IdleContext);
3476
3477 CallbackInfo->IdleCallback(CallbackInfo->IdleContext);
3478
3479 if (PortExtension->CurrentPowerState.DeviceState == PowerDeviceD0)
3480 {
3481 IsReady = FALSE;
3482 goto IdleHub;
3483 }
3484 }
3485 }
3486
3487 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING) &&
3488 (USBH_CheckIdleAbort(HubExtension, FALSE, FALSE) == TRUE))
3489 {
3490 IsReady = FALSE;
3491 }
3492
3493 IdleHub:
3494
3495 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3496 LOW_REALTIME_PRIORITY,
3497 1,
3498 FALSE);
3499
3500 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3501 {
3502 KeSetEvent(&HubExtension->PendingRequestEvent,
3503 EVENT_INCREMENT,
3504 FALSE);
3505 }
3506
3507 if (!IsReady ||
3508 (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_SUSPENDED))
3509 {
3510 DPRINT1("USBH_FdoIdleNotificationCallback: HubFlags - %lX\n",
3511 HubExtension->HubFlags);
3512
3513 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED |
3514 USBHUB_FDO_FLAG_GOING_IDLE);
3515
3516 /* Aborting Idle for Hub */
3517 IoAcquireCancelSpinLock(&OldIrql);
3518
3519 if (HubExtension->PendingIdleIrp)
3520 {
3521 Irp = HubExtension->PendingIdleIrp;
3522 HubExtension->PendingIdleIrp = NULL;
3523 }
3524
3525 IoReleaseCancelSpinLock(OldIrql);
3526
3527 if (Irp)
3528 {
3529 USBH_HubCancelIdleIrp(HubExtension, Irp);
3530 }
3531
3532 DbgBreakPoint();
3533 USBH_HubCompletePortIdleIrps(HubExtension, STATUS_CANCELLED);
3534 }
3535 else
3536 {
3537 PowerState.DeviceState = HubExtension->DeviceWake;
3538
3539 KeWaitForSingleObject(&HubExtension->IdleSemaphore,
3540 Executive,
3541 KernelMode,
3542 FALSE,
3543 NULL);
3544
3545 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_GOING_IDLE;
3546 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_SUSPENSE;
3547
3548 KeInitializeEvent(&Event, NotificationEvent, FALSE);
3549
3550 DPRINT("USBH_FdoIdleNotificationCallback: LowerPdo - %p\n",
3551 HubExtension->LowerPDO);
3552
3553 DPRINT("USBH_FdoIdleNotificationCallback: PowerState.DeviceState - %x\n",
3554 PowerState.DeviceState);
3555
3556 Status = PoRequestPowerIrp(HubExtension->LowerPDO,
3557 IRP_MN_SET_POWER,
3558 PowerState,
3559 USBH_HubSetDWakeCompletion,
3560 &Event,
3561 NULL);
3562
3563 if (Status == STATUS_PENDING)
3564 {
3565 KeWaitForSingleObject(&Event,
3566 Executive,
3567 KernelMode,
3568 FALSE,
3569 NULL);
3570 }
3571 }
3572 }
3573
3574 VOID
3575 NTAPI
3576 USBH_CompletePortIdleIrpsWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3577 IN PVOID Context)
3578 {
3579 PUSBHUB_IDLE_PORT_CONTEXT IdlePortContext;
3580 NTSTATUS NtStatus;
3581 NTSTATUS Status;
3582 BOOLEAN IsFlush = FALSE;
3583
3584 DPRINT("USBH_CompletePortIdleIrpsWorker ... \n");
3585
3586 IdlePortContext = Context;
3587 NtStatus = IdlePortContext->Status;
3588
3589 USBH_HubCompleteQueuedPortIdleIrps(HubExtension,
3590 &IdlePortContext->PwrList,
3591 NtStatus);
3592
3593 DPRINT1("USBH_CompletePortIdleIrpsWorker: USBH_RegQueryFlushPortPowerIrpsFlag() UNIMPLEMENTED. FIXME\n");
3594 Status = STATUS_NOT_IMPLEMENTED;// USBH_RegQueryFlushPortPowerIrpsFlag(&IsFlush);
3595
3596 if (NT_SUCCESS(Status))
3597 {
3598 if (IsFlush)
3599 {
3600 USBH_FlushPortPwrList(HubExtension);
3601 }
3602 }
3603 }
3604
3605 VOID
3606 NTAPI
3607 USBH_IdleCompletePowerHubWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3608 IN PVOID Context)
3609 {
3610 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer;
3611
3612 DPRINT("USBH_IdleCompletePowerHubWorker ... \n");
3613
3614 if (HubExtension &&
3615 HubExtension->CurrentPowerState.DeviceState != PowerDeviceD0 &&
3616 HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED)
3617 {
3618 USBH_HubSetD0(HubExtension);
3619 }
3620
3621 HubWorkItemBuffer = Context;
3622
3623 USBH_HubCompletePortIdleIrps(HubExtension, HubWorkItemBuffer->Status);
3624
3625 }
3626
3627 NTSTATUS
3628 NTAPI
3629 USBH_FdoIdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject,
3630 IN PIRP Irp,
3631 IN PVOID Context)
3632 {
3633 PUSBHUB_FDO_EXTENSION HubExtension;
3634 NTSTATUS NtStatus;
3635 PVOID IdleIrp;
3636 KIRQL Irql;
3637 NTSTATUS Status;
3638 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3639
3640 IoAcquireCancelSpinLock(&Irql);
3641
3642 HubExtension = Context;
3643 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3644
3645 IdleIrp = InterlockedExchangePointer((PVOID)&HubExtension->PendingIdleIrp,
3646 NULL);
3647
3648 DPRINT("USBH_FdoIdleNotificationRequestComplete: IdleIrp - %p\n", IdleIrp);
3649
3650 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3651 {
3652 KeSetEvent(&HubExtension->PendingRequestEvent, EVENT_INCREMENT, FALSE);
3653 }
3654
3655 IoReleaseCancelSpinLock(Irql);
3656
3657 NtStatus = Irp->IoStatus.Status;
3658
3659 DPRINT("USBH_FdoIdleNotificationRequestComplete: NtStatus - %lX\n",
3660 NtStatus);
3661
3662 if (!NT_SUCCESS(NtStatus) &&
3663 NtStatus != STATUS_POWER_STATE_INVALID &&
3664 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED) &&
3665 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPED))
3666 {
3667 DPRINT("USBH_FdoIdleNotificationRequestComplete: DeviceState - %x\n",
3668 HubExtension->CurrentPowerState.DeviceState);
3669
3670 if (HubExtension->CurrentPowerState.DeviceState == PowerDeviceD0)
3671 {
3672 PUSBHUB_IDLE_PORT_CONTEXT HubWorkItemBuffer;
3673
3674 Status = USBH_AllocateWorkItem(HubExtension,
3675 &HubIoWorkItem,
3676 USBH_CompletePortIdleIrpsWorker,
3677 sizeof(USBHUB_IDLE_PORT_CONTEXT),
3678 (PVOID *)&HubWorkItemBuffer,
3679 DelayedWorkQueue);
3680
3681 if (NT_SUCCESS(Status))
3682 {
3683 HubWorkItemBuffer->Status = NtStatus;
3684
3685 USBH_HubQueuePortIdleIrps(HubExtension,
3686 &HubWorkItemBuffer->PwrList);
3687
3688 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3689 }
3690 }
3691 else
3692 {
3693 PUSBHUB_IDLE_HUB_CONTEXT HubWorkItemBuffer;
3694
3695 Status = USBH_AllocateWorkItem(HubExtension,
3696 &HubIoWorkItem,
3697 USBH_IdleCompletePowerHubWorker,
3698 sizeof(USBHUB_IDLE_HUB_CONTEXT),
3699 (PVOID *)&HubWorkItemBuffer,
3700 DelayedWorkQueue);
3701
3702 if (NT_SUCCESS(Status))
3703 {
3704 HubWorkItemBuffer->Status = NtStatus;
3705 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3706 }
3707 }
3708 }
3709
3710 if (IdleIrp ||
3711 InterlockedExchange((PLONG)&HubExtension->IdleRequestLock, 1))
3712 {
3713 DPRINT("USBH_FdoIdleNotificationRequestComplete: Irp - %p\n", Irp);
3714 IoFreeIrp(Irp);
3715 }
3716
3717 return STATUS_MORE_PROCESSING_REQUIRED;
3718 }
3719
3720 NTSTATUS
3721 NTAPI
3722 USBH_FdoSubmitIdleRequestIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
3723 {
3724 NTSTATUS Status;
3725 ULONG HubFlags;
3726 PDEVICE_OBJECT LowerPDO;
3727 PIRP Irp;
3728 PIO_STACK_LOCATION IoStack;
3729 KIRQL Irql;
3730
3731 DPRINT("USBH_FdoSubmitIdleRequestIrp: HubExtension - %p, PendingIdleIrp - %p\n",
3732 HubExtension,
3733 HubExtension->PendingIdleIrp);
3734
3735 if (HubExtension->PendingIdleIrp)
3736 {
3737 Status = STATUS_DEVICE_BUSY;
3738 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3739 return Status;
3740 }
3741
3742 HubFlags = HubExtension->HubFlags;
3743
3744 if (HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
3745 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED)
3746 {
3747 HubExtension->HubFlags = HubFlags & ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3748 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3749 return STATUS_DEVICE_REMOVED;
3750 }
3751
3752 LowerPDO = HubExtension->LowerPDO;
3753
3754 HubExtension->IdleCallbackInfo.IdleCallback = USBH_FdoIdleNotificationCallback;
3755 HubExtension->IdleCallbackInfo.IdleContext = HubExtension;
3756
3757 Irp = IoAllocateIrp(LowerPDO->StackSize, FALSE);
3758
3759 if (!Irp)
3760 {
3761 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3762 Status = STATUS_INSUFFICIENT_RESOURCES;
3763
3764 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3765 return Status;
3766 }
3767
3768 IoStack = IoGetNextIrpStackLocation(Irp);
3769
3770 IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
3771
3772 IoStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(USB_IDLE_CALLBACK_INFO);
3773 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
3774 IoStack->Parameters.DeviceIoControl.Type3InputBuffer = &HubExtension->IdleCallbackInfo;
3775
3776 IoSetCompletionRoutine(Irp,
3777 USBH_FdoIdleNotificationRequestComplete,
3778 HubExtension,
3779 TRUE,
3780 TRUE,
3781 TRUE);
3782
3783 InterlockedIncrement(&HubExtension->PendingRequestCount);
3784 InterlockedExchange(&HubExtension->IdleRequestLock, 0);
3785
3786 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED |
3787 USBHUB_FDO_FLAG_GOING_IDLE);
3788
3789 Status = IoCallDriver(HubExtension->LowerPDO, Irp);
3790
3791 IoAcquireCancelSpinLock(&Irql);
3792
3793 if (Status == STATUS_PENDING &&
3794 HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
3795 {
3796 HubExtension->PendingIdleIrp = Irp;
3797 }
3798
3799 IoReleaseCancelSpinLock(Irql);
3800
3801 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3802
3803 return Status;
3804 }
3805
3806 VOID
3807 NTAPI
3808 USBH_CheckHubIdle(IN PUSBHUB_FDO_EXTENSION HubExtension)
3809 {
3810 PDEVICE_OBJECT PdoDevice;
3811 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
3812 PUSBHUB_PORT_DATA PortData;
3813 ULONG HubFlags;
3814 ULONG Port;
3815 KIRQL Irql;
3816 BOOLEAN IsHubIdle = FALSE;
3817 BOOLEAN IsAllPortsIdle;
3818 BOOLEAN IsHubCheck = TRUE;
3819
3820 DPRINT("USBH_CheckHubIdle: FIXME !!! HubExtension - %p\n", HubExtension);
3821
3822 return; //HACK: delete it line after fixing Power Manager!!!
3823
3824 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3825
3826 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_CHECK_IDLE_LOCK)
3827 {
3828 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3829 return;
3830 }
3831
3832 HubExtension->HubFlags |= USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3833 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3834
3835 if (USBH_GetRootHubExtension(HubExtension)->SystemPowerState.SystemState != PowerSystemWorking)
3836 {
3837 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3838 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3839 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3840 return;
3841 }
3842
3843 HubFlags = HubExtension->HubFlags;
3844 DPRINT("USBH_CheckHubIdle: HubFlags - %lX\n", HubFlags);
3845
3846 if (!(HubFlags & USBHUB_FDO_FLAG_DEVICE_STARTED) ||
3847 !(HubFlags & USBHUB_FDO_FLAG_DO_ENUMERATION))
3848 {
3849 goto Exit;
3850 }
3851
3852 if (HubFlags & USBHUB_FDO_FLAG_NOT_ENUMERATED ||
3853 HubFlags & USBHUB_FDO_FLAG_ENUM_POST_RECOVER ||
3854 HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED ||
3855 HubFlags & USBHUB_FDO_FLAG_DEVICE_STOPPING ||
3856 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED ||
3857 HubFlags & USBHUB_FDO_FLAG_STATE_CHANGING ||
3858 HubFlags & USBHUB_FDO_FLAG_WAKEUP_START ||
3859 HubFlags & USBHUB_FDO_FLAG_ESD_RECOVERING)
3860 {
3861 goto Exit;
3862 }
3863
3864 if (HubExtension->ResetRequestCount)
3865 {
3866 HubExtension->HubFlags |= USBHUB_FDO_FLAG_DEFER_CHECK_IDLE;
3867 goto Exit;
3868 }
3869
3870 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_DEFER_CHECK_IDLE;
3871
3872 InterlockedIncrement(&HubExtension->PendingRequestCount);
3873
3874 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
3875 Executive,
3876 KernelMode,
3877 FALSE,
3878 NULL);
3879
3880 IoAcquireCancelSpinLock(&Irql);
3881
3882 IsAllPortsIdle = TRUE;
3883
3884 PortData = HubExtension->PortData;
3885
3886 for (Port = 0;
3887 Port < HubExtension->HubDescriptor->bNumberOfPorts;
3888 Port++)
3889 {
3890 PdoDevice = PortData[Port].DeviceObject;
3891
3892 if (PdoDevice)
3893 {
3894 PortExtension = PdoDevice->DeviceExtension;
3895
3896 if (!PortExtension->IdleNotificationIrp)
3897 {
3898 DPRINT("USBH_CheckHubIdle: PortExtension - %p\n",
3899 PortExtension);
3900
3901 IsAllPortsIdle = FALSE;
3902 IsHubCheck = FALSE;
3903
3904 break;
3905 }
3906 }
3907 }
3908
3909 if (IsHubCheck &&
3910 !(HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST))
3911 {
3912 KeClearEvent(&HubExtension->IdleEvent);
3913 HubExtension->HubFlags |= USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST;
3914 IsHubIdle = TRUE;
3915 }
3916
3917 IoReleaseCancelSpinLock(Irql);
3918
3919 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3920 LOW_REALTIME_PRIORITY,
3921 1,
3922 FALSE);
3923
3924 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3925 {
3926 KeSetEvent(&HubExtension->PendingRequestEvent,
3927 EVENT_INCREMENT,
3928 FALSE);
3929 }
3930
3931 DPRINT("USBH_CheckHubIdle: IsAllPortsIdle - %x, IsHubIdle - %x\n",
3932 IsAllPortsIdle,
3933 IsHubIdle);
3934
3935 if (IsAllPortsIdle && IsHubIdle)
3936 {
3937 USBH_FdoSubmitIdleRequestIrp(HubExtension);
3938 }
3939
3940 Exit:
3941 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3942 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3943 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3944 }
3945
3946 VOID
3947 NTAPI
3948 USBH_CheckIdleWorker(IN PUSBHUB_FDO_EXTENSION HubExtension,
3949 IN PVOID Context)
3950 {
3951 DPRINT("USBH_CheckIdleWorker: ... \n");
3952 USBH_CheckHubIdle(HubExtension);
3953 }
3954
3955 VOID
3956 NTAPI
3957 USBH_CheckIdleDeferred(IN PUSBHUB_FDO_EXTENSION HubExtension)
3958 {
3959 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3960 NTSTATUS Status;
3961
3962 DPRINT("USBH_CheckIdleDeferred: HubExtension - %p\n", HubExtension);
3963
3964 Status = USBH_AllocateWorkItem(HubExtension,
3965 &HubIoWorkItem,
3966 USBH_CheckIdleWorker,
3967 0,
3968 NULL,
3969 DelayedWorkQueue);
3970
3971 DPRINT("USBH_CheckIdleDeferred: HubIoWorkItem - %p\n", HubIoWorkItem);
3972
3973 if (NT_SUCCESS(Status))
3974 {
3975 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3976 }
3977 }
3978
3979 VOID
3980 NTAPI
3981 USBH_PdoSetCapabilities(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension)
3982 {
3983 PUSBHUB_FDO_EXTENSION HubExtension;
3984 ULONG State;
3985 SYSTEM_POWER_STATE SystemPowerState;
3986 PDEVICE_POWER_STATE pDeviceState;
3987
3988 DPRINT("USBH_PdoSetCapabilities ... \n");
3989
3990 HubExtension = PortExtension->HubExtension;
3991
3992 PortExtension->Capabilities.Size = 64;
3993 PortExtension->Capabilities.Version = 1;
3994
3995 PortExtension->Capabilities.Removable = 1;
3996 PortExtension->Capabilities.Address = PortExtension->PortNumber;
3997
3998 if (PortExtension->SerialNumber)
3999 {
4000 PortExtension->Capabilities.UniqueID = 1;
4001 }
4002 else
4003 {
4004 PortExtension->Capabilities.UniqueID = 0;
4005 }
4006
4007 PortExtension->Capabilities.RawDeviceOK = 0;
4008
4009 RtlCopyMemory(PortExtension->Capabilities.DeviceState,
4010 HubExtension->DeviceState,
4011 (PowerSystemMaximum + 2) * sizeof(POWER_STATE));
4012
4013 PortExtension->Capabilities.DeviceState[1] = PowerDeviceD0;
4014
4015 if (PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOTE_WAKEUP)
4016 {
4017 PortExtension->Capabilities.DeviceWake = PowerDeviceD2;
4018
4019 PortExtension->Capabilities.DeviceD1 = 1;
4020 PortExtension->Capabilities.DeviceD2 = 1;
4021
4022 PortExtension->Capabilities.WakeFromD0 = 1;
4023 PortExtension->Capabilities.WakeFromD1 = 1;
4024 PortExtension->Capabilities.WakeFromD2 = 1;
4025
4026 pDeviceState = &PortExtension->Capabilities.DeviceState[2];
4027
4028 for (State = 2; State <= 5; State++)
4029 {
4030 SystemPowerState = State;
4031
4032 if (PortExtension->Capabilities.SystemWake < SystemPowerState)
4033 {
4034 *pDeviceState = PowerDeviceD3;
4035 }
4036 else
4037 {
4038 *pDeviceState = PowerDeviceD2;
4039 }
4040
4041 ++pDeviceState;
4042 }
4043 }
4044 else
4045 {
4046 PortExtension->Capabilities.DeviceWake = PowerDeviceD0;
4047 PortExtension->Capabilities.DeviceState[2] = PowerDeviceD3;
4048 PortExtension->Capabilities.DeviceState[3] = PowerDeviceD3;
4049 PortExtension->Capabilities.DeviceState[4] = PowerDeviceD3;
4050 PortExtension->Capabilities.DeviceState[5] = PowerDeviceD3;
4051 }
4052 }
4053
4054 NTSTATUS
4055 NTAPI
4056 USBH_ProcessDeviceInformation(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension)
4057 {
4058 PUSB_INTERFACE_DESCRIPTOR Pid;
4059 PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
4060 NTSTATUS Status;
4061
4062 DPRINT("USBH_ProcessDeviceInformation ... \n");
4063
4064 ConfigDescriptor = NULL;
4065
4066 RtlZeroMemory(&PortExtension->InterfaceDescriptor,
4067 sizeof(PortExtension->InterfaceDescriptor));
4068
4069 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_HUB_DEVICE;
4070
4071 Status = USBH_GetConfigurationDescriptor(PortExtension->Common.SelfDevice,
4072 &ConfigDescriptor);
4073
4074 if (!NT_SUCCESS(Status))
4075 {
4076 if (ConfigDescriptor)
4077 {
4078 ExFreePool(ConfigDescriptor);
4079 }
4080
4081 return Status;
4082 }
4083
4084 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOTE_WAKEUP;
4085
4086 if (ConfigDescriptor->bmAttributes & 0x20)
4087 {
4088 /* device configuration supports remote wakeup */
4089 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOTE_WAKEUP;
4090 }
4091
4092 USBHUB_DumpingDeviceDescriptor(&PortExtension->DeviceDescriptor);
4093 USBHUB_DumpingConfiguration(ConfigDescriptor);
4094
4095 DPRINT_PNP("USBH_ProcessDeviceInformation: Class - %x, SubClass - %x, Protocol - %x\n",
4096 PortExtension->DeviceDescriptor.bDeviceClass,
4097 PortExtension->DeviceDescriptor.bDeviceSubClass,
4098 PortExtension->DeviceDescriptor.bDeviceProtocol);
4099
4100 DPRINT_PNP("USBH_ProcessDeviceInformation: bNumConfigurations - %x, bNumInterfaces - %x\n",
4101 PortExtension->DeviceDescriptor.bNumConfigurations,
4102 ConfigDescriptor->bNumInterfaces);
4103
4104
4105 /* Enumeration of USB Composite Devices (msdn):
4106 1) The device class field of the device descriptor (bDeviceClass) must contain a value of zero,
4107 or the class (bDeviceClass), subclass (bDeviceSubClass), and protocol (bDeviceProtocol)
4108 fields of the device descriptor must have the values 0xEF, 0x02 and 0x01 respectively,
4109 as explained in USB Interface Association Descriptor.
4110 2) The device must have multiple interfaces
4111 3) The device must have a single configuration.
4112 */
4113
4114 if (((PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_RESERVED) ||
4115 (PortExtension->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_MISCELLANEOUS &&
4116 PortExtension->DeviceDescriptor.bDeviceSubClass == 0x02 &&
4117 PortExtension->DeviceDescriptor.bDeviceProtocol == 0x01)) &&
4118 (ConfigDescriptor->bNumInterfaces > 1) &&
4119 (PortExtension->DeviceDescriptor.bNumConfigurations < 2))
4120 {
4121 DPRINT("USBH_ProcessDeviceInformation: Multi-Interface configuration\n");
4122
4123 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_MULTI_INTERFACE;
4124
4125 if (ConfigDescriptor)
4126 {
4127 ExFreePool(ConfigDescriptor);
4128 }
4129
4130 return Status;
4131 }
4132
4133 Pid = USBD_ParseConfigurationDescriptorEx(ConfigDescriptor,
4134 ConfigDescriptor,
4135 -1,
4136 -1,
4137 -1,
4138 -1,
4139 -1);
4140 if (Pid)
4141 {
4142 RtlCopyMemory(&PortExtension->InterfaceDescriptor,
4143 Pid,
4144 sizeof(PortExtension->InterfaceDescriptor));
4145
4146 if (Pid->bInterfaceClass == USB_DEVICE_CLASS_HUB)
4147 {
4148 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_HUB_DEVICE |
4149 USBHUB_PDO_FLAG_REMOTE_WAKEUP);
4150 }
4151 }
4152 else
4153 {
4154 Status = STATUS_UNSUCCESSFUL;
4155 }
4156
4157 if (ConfigDescriptor)
4158 {
4159 ExFreePool(ConfigDescriptor);
4160 }
4161
4162 return Status;
4163 }
4164
4165 BOOLEAN
4166 NTAPI
4167 USBH_CheckDeviceIDUnique(IN PUSBHUB_FDO_EXTENSION HubExtension,
4168 IN USHORT idVendor,
4169 IN USHORT idProduct,
4170 IN PVOID SerialNumber,
4171 IN USHORT SN_DescriptorLength)
4172 {
4173 PDEVICE_OBJECT PortDevice;
4174 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4175 ULONG Port;
4176 SIZE_T NumberBytes;
4177
4178 DPRINT("USBH_CheckDeviceIDUnique: idVendor - 0x%04X, idProduct - 0x%04X\n",
4179 idVendor,
4180 idProduct);
4181
4182 if (!HubExtension->HubDescriptor->bNumberOfPorts)
4183 {
4184 return TRUE;
4185 }
4186
4187 for (Port = 0; Port < HubExtension->HubDescriptor->bNumberOfPorts; Port++)
4188 {
4189 PortDevice = HubExtension->PortData[Port].DeviceObject;
4190
4191 if (PortDevice)
4192 {
4193 PortExtension = PortDevice->DeviceExtension;
4194
4195 if (PortExtension->DeviceDescriptor.idVendor == idVendor &&
4196 PortExtension->DeviceDescriptor.idProduct == idProduct &&
4197 PortExtension->SN_DescriptorLength == SN_DescriptorLength)
4198 {
4199 if (PortExtension->SerialNumber)
4200 {
4201 NumberBytes = RtlCompareMemory(PortExtension->SerialNumber,
4202 SerialNumber,
4203 SN_DescriptorLength);
4204
4205 if (NumberBytes == SN_DescriptorLength)
4206 {
4207 return FALSE;
4208 }
4209 }
4210 }
4211 }
4212 }
4213
4214 return TRUE;
4215 }
4216
4217 BOOLEAN
4218 NTAPI
4219 USBH_ValidateSerialNumberString(IN PUSHORT SerialNumberString)
4220 {
4221 USHORT ix;
4222 USHORT Symbol;
4223
4224 DPRINT("USBH_ValidateSerialNumberString: ... \n");
4225
4226 for (ix = 0; SerialNumberString[ix] != UNICODE_NULL; ix++)
4227 {
4228 Symbol = SerialNumberString[ix];
4229
4230 if (Symbol < 0x20 || Symbol > 0x7F || Symbol == 0x2C) // ','
4231 {
4232 return FALSE;
4233 }
4234 }
4235
4236 return TRUE;
4237 }
4238
4239
4240 NTSTATUS
4241 NTAPI
4242 USBH_CheckDeviceLanguage(IN PDEVICE_OBJECT DeviceObject,
4243 IN USHORT LanguageId)
4244 {
4245 PUSB_STRING_DESCRIPTOR Descriptor;
4246 NTSTATUS Status;
4247 ULONG NumSymbols;
4248 ULONG ix;
4249 PWCHAR pSymbol;
4250 ULONG Length;
4251
4252 DPRINT("USBH_CheckDeviceLanguage: LanguageId - 0x%04X\n", LanguageId);
4253
4254 Descriptor = ExAllocatePoolWithTag(NonPagedPool,
4255 MAXIMUM_USB_STRING_LENGTH,
4256 USB_HUB_TAG);
4257
4258 if (!Descriptor)
4259 {
4260 return STATUS_INSUFFICIENT_RESOURCES;
4261 }
4262
4263 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH);
4264
4265 Status = USBH_SyncGetStringDescriptor(DeviceObject,
4266 0,
4267 0,
4268 Descriptor,
4269 MAXIMUM_USB_STRING_LENGTH,
4270 &Length,
4271 TRUE);
4272
4273 if (!NT_SUCCESS(Status) ||
4274 Length < sizeof(USB_COMMON_DESCRIPTOR))
4275 {
4276 goto Exit;
4277 }
4278
4279 NumSymbols = (Length -
4280 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / sizeof(WCHAR);
4281
4282 pSymbol = Descriptor->bString;
4283
4284 for (ix = 1; ix < NumSymbols; ix++)
4285 {
4286 if (*pSymbol == (WCHAR)LanguageId)
4287 {
4288 Status = STATUS_SUCCESS;
4289 goto Exit;
4290 }
4291
4292 pSymbol++;
4293 }
4294
4295 Status = STATUS_NOT_SUPPORTED;
4296
4297 Exit:
4298 ExFreePoolWithTag(Descriptor, USB_HUB_TAG);
4299 return Status;
4300 }
4301
4302 NTSTATUS
4303 NTAPI
4304 USBH_GetSerialNumberString(IN PDEVICE_OBJECT DeviceObject,
4305 IN LPWSTR * OutSerialNumber,
4306 IN PUSHORT OutDescriptorLength,
4307 IN USHORT LanguageId,
4308 IN UCHAR Index)
4309 {
4310 PUSB_STRING_DESCRIPTOR Descriptor;
4311 NTSTATUS Status;
4312 LPWSTR SerialNumberBuffer = NULL;
4313 UCHAR StringLength;
4314 UCHAR Length;
4315
4316 DPRINT("USBH_GetSerialNumberString: ... \n");
4317
4318 *OutSerialNumber = NULL;
4319 *OutDescriptorLength = 0;
4320
4321 Descriptor = ExAllocatePoolWithTag(NonPagedPool,
4322 MAXIMUM_USB_STRING_LENGTH,
4323 USB_HUB_TAG);
4324
4325 if (!Descriptor)
4326 {
4327 return STATUS_INSUFFICIENT_RESOURCES;
4328 }
4329
4330 RtlZeroMemory(Descriptor, MAXIMUM_USB_STRING_LENGTH);
4331
4332 Status = USBH_CheckDeviceLanguage(DeviceObject, LanguageId);
4333
4334 if (!NT_SUCCESS(Status))
4335 {
4336 goto Exit;
4337 }
4338
4339 Status = USBH_SyncGetStringDescriptor(DeviceObject,
4340 Index,
4341 LanguageId,
4342 Descriptor,
4343 MAXIMUM_USB_STRING_LENGTH,
4344 NULL,
4345 TRUE);
4346
4347 if (!NT_SUCCESS(Status) ||
4348 Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR))
4349 {
4350 Status = STATUS_INSUFFICIENT_RESOURCES;
4351 goto Exit;
4352 }
4353
4354 StringLength = Descriptor->bLength -
4355 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString);
4356
4357 Length = StringLength + sizeof(UNICODE_NULL);
4358
4359 SerialNumberBuffer = ExAllocatePoolWithTag(PagedPool, Length, USB_HUB_TAG);
4360
4361 if (!SerialNumberBuffer)
4362 {
4363 goto Exit;
4364 }
4365
4366 RtlZeroMemory(SerialNumberBuffer, Length);
4367 RtlCopyMemory(SerialNumberBuffer, Descriptor->bString, StringLength);
4368
4369 *OutSerialNumber = SerialNumberBuffer;
4370 *OutDescriptorLength = Length;
4371
4372 Exit:
4373 ExFreePoolWithTag(Descriptor, USB_HUB_TAG);
4374 return Status;
4375 }
4376
4377 NTSTATUS
4378 NTAPI
4379 USBH_CreateDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
4380 IN USHORT Port,
4381 IN USB_PORT_STATUS UsbPortStatus,
4382 IN ULONG IsWait)
4383 {
4384 ULONG PdoNumber = 0;
4385 WCHAR CharDeviceName[64];
4386 UNICODE_STRING DeviceName;
4387 PDEVICE_OBJECT DeviceObject = NULL;
4388 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4389 PUSB_DEVICE_HANDLE DeviceHandle;
4390 LPWSTR SerialNumberBuffer;
4391 BOOLEAN IsHsDevice;
4392 BOOLEAN IsLsDevice;
4393 BOOLEAN IgnoringHwSerial = FALSE;
4394 NTSTATUS Status;
4395 UNICODE_STRING DestinationString;
4396
4397 DPRINT("USBH_CreateDevice: Port - %x, UsbPortStatus - %lX\n",
4398 Port,
4399 UsbPortStatus.AsUshort16);
4400
4401 do
4402 {
4403 RtlStringCbPrintfW(CharDeviceName,
4404 sizeof(CharDeviceName),
4405 L"\\Device\\USBPDO-%d",
4406 PdoNumber);
4407
4408 RtlInitUnicodeString(&DeviceName, CharDeviceName);
4409
4410 Status = IoCreateDevice(HubExtension->Common.SelfDevice->DriverObject,
4411 sizeof(USBHUB_PORT_PDO_EXTENSION),
4412 &DeviceName,
4413 FILE_DEVICE_USB,
4414 0,
4415 FALSE,
4416 &DeviceObject);
4417
4418 ++PdoNumber;
4419 }
4420 while (Status == STATUS_OBJECT_NAME_COLLISION);
4421
4422 if (!NT_SUCCESS(Status))
4423 {
4424 ASSERT(Port > 0);
4425 HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4426 return Status;
4427 }
4428
4429 DeviceObject->StackSize = HubExtension->RootHubPdo2->StackSize;
4430
4431 PortExtension = DeviceObject->DeviceExtension;
4432
4433 DPRINT("USBH_CreateDevice: PortDevice - %p, <%wZ>\n", DeviceObject, &DeviceName);
4434 DPRINT("USBH_CreateDevice: PortExtension - %p\n", PortExtension);
4435
4436 RtlZeroMemory(PortExtension, sizeof(USBHUB_PORT_PDO_EXTENSION));
4437
4438 PortExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_PORT;
4439 PortExtension->Common.SelfDevice = DeviceObject;
4440
4441 PortExtension->HubExtension = HubExtension;
4442 PortExtension->RootHubExtension = HubExtension;
4443
4444 PortExtension->PortNumber = Port;
4445 PortExtension->CurrentPowerState.DeviceState = PowerDeviceD0;
4446 PortExtension->IgnoringHwSerial = FALSE;
4447
4448 KeInitializeSpinLock(&PortExtension->PortTimeoutSpinLock);
4449
4450 InitializeListHead(&PortExtension->PortPowerList);
4451 KeInitializeSpinLock(&PortExtension->PortPowerListSpinLock);
4452
4453 PortExtension->PoRequestCounter = 0;
4454 PortExtension->PendingSystemPoRequest = 0;
4455 PortExtension->PendingDevicePoRequest = 0;
4456 PortExtension->StateBehindD2 = 0;
4457
4458 SerialNumberBuffer = NULL;
4459
4460 IsHsDevice = UsbPortStatus.Usb20PortStatus.HighSpeedDeviceAttached;
4461 IsLsDevice = UsbPortStatus.Usb20PortStatus.LowSpeedDeviceAttached;
4462
4463 if (IsLsDevice == 0)
4464 {
4465 if (IsHsDevice)
4466 {
4467 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_HIGH_SPEED;
4468 }
4469 }
4470 else
4471 {
4472 PortExtension->PortPdoFlags = USBHUB_PDO_FLAG_PORT_LOW_SPEED;
4473 }
4474
4475 /* Initialize PortExtension->InstanceID */
4476 RtlInitUnicodeString(&DestinationString, (PCWSTR)&PortExtension->InstanceID);
4477 DestinationString.MaximumLength = 4 * sizeof(WCHAR);
4478 Status = RtlIntegerToUnicodeString(Port, 10, &DestinationString);
4479
4480 DeviceObject->Flags |= DO_POWER_PAGABLE;
4481 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4482
4483 if (!NT_SUCCESS(Status))
4484 {
4485 DPRINT1("USBH_CreateDevice: IoCreateDevice() failed - %lX\n", Status);
4486 goto ErrorExit;
4487 }
4488
4489 Status = USBD_CreateDeviceEx(HubExtension,
4490 &PortExtension->DeviceHandle,
4491 UsbPortStatus,
4492 Port);
4493
4494 if (!NT_SUCCESS(Status))
4495 {
4496 DPRINT1("USBH_CreateDevice: USBD_CreateDeviceEx() failed - %lX\n", Status);
4497 goto ErrorExit;
4498 }
4499
4500 Status = USBH_SyncResetPort(HubExtension, Port);
4501
4502 if (!NT_SUCCESS(Status))
4503 {
4504 DPRINT1("USBH_CreateDevice: USBH_SyncResetPort() failed - %lX\n", Status);
4505 goto ErrorExit;
4506 }
4507
4508 if (IsWait)
4509 {
4510 USBH_Wait(50);
4511 }
4512
4513 Status = USBD_InitializeDeviceEx(HubExtension,
4514 PortExtension->DeviceHandle,
4515 (PUCHAR)&PortExtension->DeviceDescriptor,
4516 sizeof(USB_DEVICE_DESCRIPTOR),
4517 (PUCHAR)&PortExtension->ConfigDescriptor,
4518 sizeof(USB_CONFIGURATION_DESCRIPTOR));
4519
4520 if (!NT_SUCCESS(Status))
4521 {
4522 DPRINT1("USBH_CreateDevice: USBD_InitializeDeviceEx() failed - %lX\n", Status);
4523 PortExtension->DeviceHandle = NULL;
4524 goto ErrorExit;
4525 }
4526
4527 DPRINT1("USBH_RegQueryDeviceIgnoreHWSerNumFlag UNIMPLEMENTED. FIXME\n");
4528 //Status = USBH_RegQueryDeviceIgnoreHWSerNumFlag(PortExtension->DeviceDescriptor.idVendor,
4529 // PortExtension->DeviceDescriptor.idProduct,
4530 // &IgnoringHwSerial);
4531
4532 if (TRUE)//Status == STATUS_OBJECT_NAME_NOT_FOUND)
4533 {
4534 IgnoringHwSerial = FALSE;
4535 }
4536
4537 if (IgnoringHwSerial)
4538 {
4539 PortExtension->IgnoringHwSerial = TRUE;
4540 }
4541
4542 if (PortExtension->DeviceDescriptor.iSerialNumber &&
4543 !PortExtension->IgnoringHwSerial)
4544 {
4545 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber, NULL);
4546
4547 USBH_GetSerialNumberString(PortExtension->Common.SelfDevice,
4548 &SerialNumberBuffer,
4549 &PortExtension->SN_DescriptorLength,
4550 MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
4551 PortExtension->DeviceDescriptor.iSerialNumber);
4552
4553 if (SerialNumberBuffer)
4554 {
4555 if (!USBH_ValidateSerialNumberString((PUSHORT)SerialNumberBuffer))
4556 {
4557 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4558 SerialNumberBuffer = NULL;
4559 }
4560
4561 if (SerialNumberBuffer &&
4562 !USBH_CheckDeviceIDUnique(HubExtension,
4563 PortExtension->DeviceDescriptor.idVendor,
4564 PortExtension->DeviceDescriptor.idProduct,
4565 SerialNumberBuffer,
4566 PortExtension->SN_DescriptorLength))
4567 {
4568 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4569 SerialNumberBuffer = NULL;
4570 }
4571 }
4572
4573 InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
4574 SerialNumberBuffer);
4575 }
4576
4577 Status = USBH_ProcessDeviceInformation(PortExtension);
4578
4579 USBH_PdoSetCapabilities(PortExtension);
4580
4581 if (NT_SUCCESS(Status))
4582 {
4583 goto Exit;
4584 }
4585
4586 ErrorExit:
4587
4588 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_INIT_PORT_FAILED;
4589
4590 DeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
4591 NULL);
4592
4593 if (DeviceHandle)
4594 {
4595 USBD_RemoveDeviceEx(HubExtension, DeviceHandle, 0);
4596 }
4597
4598 SerialNumberBuffer = InterlockedExchangePointer((PVOID)&PortExtension->SerialNumber,
4599 NULL);
4600
4601 if (SerialNumberBuffer)
4602 {
4603 ExFreePoolWithTag(SerialNumberBuffer, USB_HUB_TAG);
4604 }
4605
4606 Exit:
4607
4608 ASSERT(Port > 0);
4609 HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4610 return Status;
4611 }
4612
4613 NTSTATUS
4614 NTAPI
4615 USBH_ResetDevice(IN PUSBHUB_FDO_EXTENSION HubExtension,
4616 IN USHORT Port,
4617 IN BOOLEAN IsKeepDeviceData,
4618 IN BOOLEAN IsWait)
4619 {
4620 NTSTATUS Status;
4621 PUSBHUB_PORT_DATA PortData;
4622 PDEVICE_OBJECT PortDevice;
4623 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4624 PVOID NewDeviceHandle;
4625 PVOID Handle;
4626 PVOID OldDeviceHandle;
4627 PUSB_DEVICE_HANDLE * DeviceHandle;
4628 USB_PORT_STATUS_AND_CHANGE PortStatus;
4629
4630 DPRINT("USBH_ResetDevice: HubExtension - %p, Port - %x, IsKeepDeviceData - %x, IsWait - %x\n",
4631 HubExtension,
4632 Port,
4633 IsKeepDeviceData,
4634 IsWait);
4635
4636 Status = USBH_SyncGetPortStatus(HubExtension,
4637 Port,
4638 &PortStatus,
4639 sizeof(USB_PORT_STATUS_AND_CHANGE));
4640
4641 if (!NT_SUCCESS(Status) ||
4642 !(PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus))
4643 {
4644 return STATUS_UNSUCCESSFUL;
4645 }
4646
4647 InterlockedIncrement(&HubExtension->PendingRequestCount);
4648
4649 KeWaitForSingleObject(&HubExtension->ResetDeviceSemaphore,
4650 Executive,
4651 KernelMode,
4652 FALSE,
4653 NULL);
4654
4655 ASSERT(Port > 0);
4656 PortData = &HubExtension->PortData[Port-1];
4657
4658 PortDevice = PortData->DeviceObject;
4659
4660 if (!PortDevice)
4661 {
4662 Status = STATUS_INVALID_PARAMETER;
4663
4664 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4665 LOW_REALTIME_PRIORITY,
4666 1,
4667 FALSE);
4668
4669 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4670 {
4671 KeSetEvent(&HubExtension->PendingRequestEvent,
4672 EVENT_INCREMENT,
4673 FALSE);
4674 }
4675
4676 return Status;
4677 }
4678
4679 PortExtension = PortDevice->DeviceExtension;
4680 DeviceHandle = &PortExtension->DeviceHandle;
4681
4682 OldDeviceHandle = InterlockedExchangePointer(&PortExtension->DeviceHandle,
4683 NULL);
4684
4685 if (OldDeviceHandle)
4686 {
4687 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOVING_PORT_PDO))
4688 {
4689 Status = USBD_RemoveDeviceEx(HubExtension,
4690 OldDeviceHandle,
4691 IsKeepDeviceData);
4692
4693 PortExtension->PortPdoFlags |= USBHUB_PDO_FLAG_REMOVING_PORT_PDO;
4694 }
4695 }
4696 else
4697 {
4698 OldDeviceHandle = NULL;
4699 }
4700
4701 if (!NT_SUCCESS(Status))
4702 {
4703 goto ErrorExit;
4704 }
4705
4706 Status = USBH_SyncResetPort(HubExtension, Port);
4707
4708 if (!NT_SUCCESS(Status))
4709 {
4710 goto ErrorExit;
4711 }
4712
4713 Status = USBH_SyncGetPortStatus(HubExtension,
4714 Port,
4715 &PortStatus,
4716 sizeof(USB_PORT_STATUS_AND_CHANGE));
4717
4718 if (!NT_SUCCESS(Status))
4719 {
4720 goto ErrorExit;
4721 }
4722
4723 Status = USBD_CreateDeviceEx(HubExtension,
4724 DeviceHandle,
4725 PortStatus.PortStatus,
4726 Port);
4727
4728 if (!NT_SUCCESS(Status))
4729 {
4730 goto ErrorExit;
4731 }
4732
4733 Status = USBH_SyncResetPort(HubExtension, Port);
4734
4735 if (IsWait)
4736 {
4737 USBH_Wait(50);
4738 }
4739
4740 if (!NT_SUCCESS(Status))
4741 {
4742 goto ErrorExit;
4743 }
4744
4745 Status = USBD_InitializeDeviceEx(HubExtension,
4746 *DeviceHandle,
4747 &PortExtension->DeviceDescriptor.bLength,
4748 sizeof(PortExtension->DeviceDescriptor),
4749 &PortExtension->ConfigDescriptor.bLength,
4750 sizeof(PortExtension->ConfigDescriptor));
4751
4752 if (NT_SUCCESS(Status))
4753 {
4754 if (IsKeepDeviceData)
4755 {
4756 Status = USBD_RestoreDeviceEx(HubExtension,
4757 OldDeviceHandle,
4758 *DeviceHandle);
4759
4760 if (!NT_SUCCESS(Status))
4761 {
4762 Handle = InterlockedExchangePointer(DeviceHandle, NULL);
4763
4764 USBD_RemoveDeviceEx(HubExtension, Handle, 0);
4765 USBH_SyncDisablePort(HubExtension, Port);
4766
4767 Status = STATUS_NO_SUCH_DEVICE;
4768 }
4769 }
4770 else
4771 {
4772 PortExtension->PortPdoFlags &= ~USBHUB_PDO_FLAG_REMOVING_PORT_PDO;
4773 }
4774
4775 goto Exit;
4776 }
4777
4778 *DeviceHandle = NULL;
4779
4780 ErrorExit:
4781
4782 NewDeviceHandle = InterlockedExchangePointer(DeviceHandle,
4783 OldDeviceHandle);
4784
4785 if (NewDeviceHandle)
4786 {
4787 Status = USBD_RemoveDeviceEx(HubExtension, NewDeviceHandle, 0);
4788 }
4789
4790 Exit:
4791
4792 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4793 LOW_REALTIME_PRIORITY,
4794 1,
4795 FALSE);
4796
4797 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4798 {
4799 KeSetEvent(&HubExtension->PendingRequestEvent,
4800 EVENT_INCREMENT,
4801 FALSE);
4802 }
4803
4804 return Status;
4805 }
4806
4807 NTSTATUS
4808 NTAPI
4809 USBH_PdoDispatch(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension,
4810 IN PIRP Irp)
4811 {
4812 PIO_STACK_LOCATION IoStack;
4813 UCHAR MajorFunction;
4814 BOOLEAN ShouldCompleteIrp;
4815 ULONG ControlCode;
4816 NTSTATUS Status;
4817
4818 IoStack = IoGetCurrentIrpStackLocation(Irp);
4819 MajorFunction = IoStack->MajorFunction;
4820
4821 switch (MajorFunction)
4822 {
4823 case IRP_MJ_CREATE:
4824 case IRP_MJ_CLOSE:
4825 DPRINT("USBH_PdoDispatch: IRP_MJ_CREATE / IRP_MJ_CLOSE (%d)\n",
4826 MajorFunction);
4827 Status = STATUS_SUCCESS;
4828 USBH_CompleteIrp(Irp, Status);
4829 break;
4830
4831 case IRP_MJ_DEVICE_CONTROL:
4832 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
4833 DPRINT("USBH_PdoDispatch: IRP_MJ_DEVICE_CONTROL ControlCode - %x\n",
4834 ControlCode);
4835
4836 if (ControlCode == IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
4837 {
4838 Status = STATUS_NOT_SUPPORTED;
4839 USBH_CompleteIrp(Irp, Status);
4840 break;
4841 }
4842