ReactOS 0.4.16-dev-320-g3bd9ddc
usbhub.c
Go to the documentation of this file.
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
20
23USBH_Wait(IN ULONG Milliseconds)
24{
26
27 DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds);
28 Interval.QuadPart = -10000LL * Milliseconds - ((ULONGLONG)KeQueryTimeIncrement() - 1);
30}
31
40{
42
43 DPRINT("USBHUB_GetConfigValue: ... \n");
44
45 if (ValueType == REG_BINARY)
46 {
48 }
49 else if (ValueType == REG_DWORD)
50 {
52 }
53 else
54 {
56 }
57
58 return Status;
59}
60
61VOID
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;
75}
76
80 IN PIRP Irp)
81{
82 DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n",
84 Irp);
85
88}
89
93 IN PIRP Irp,
95{
96 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
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,
113 FALSE);
114 }
115
116 return STATUS_SUCCESS;
117}
118
120NTAPI
121IsBitSet(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
132NTAPI
134{
136
137 DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject);
138
139 if (DeviceObject)
140 {
141 PdoExtension = DeviceObject->DeviceExtension;
142 }
143 else
144 {
146 }
147
149}
150
152NTAPI
154 IN ULONG FailReason)
155{
159
160 DPRINT("USBH_WriteFailReason: ID - %x\n", FailReason);
161
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
177 }
178
179 return Status;
180}
181
182VOID
183NTAPI
188{
189 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
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,
208 FALSE);
209}
210
212NTAPI
215 IN PVOID Data,
217 IN ULONG Type,
219{
221 UNICODE_STRING ValueNameString;
223
224 DPRINT("USBH_SetPdoRegistryParameter ... \n");
225
226 RtlInitUnicodeString(&ValueNameString, ValueName);
227
231 &KeyHandle);
232
233 if (NT_SUCCESS(Status))
234 {
235 ZwSetValueKey(KeyHandle,
236 &ValueNameString,
237 0,
238 Type,
239 Data,
240 DataSize);
241
243 }
244
245 return Status;
246}
247
249NTAPI
251 IN PURB Urb)
252{
255 PIRP Irp;
256 PIO_STACK_LOCATION IoStack;
257 PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
258 BOOLEAN IsWaitTimeout = FALSE;
261
262 DPRINT("USBH_SyncSubmitUrb: ... \n");
263
264 Urb->UrbHeader.UsbdDeviceHandle = NULL;
265
267
270 NULL,
271 0,
272 NULL,
273 0,
274 TRUE,
275 &Event,
277
278 if (!Irp)
279 {
281 }
282
284 IoStack->Parameters.Others.Argument1 = Urb;
285
286 HubTimeoutContext = ExAllocatePoolWithTag(NonPagedPool,
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,
299 FALSE);
300
301 KeInitializeSpinLock(&HubTimeoutContext->UrbTimeoutSpinLock);
302 KeInitializeTimer(&HubTimeoutContext->UrbTimeoutTimer);
303
304 KeInitializeDpc(&HubTimeoutContext->UrbTimeoutDPC,
306 HubTimeoutContext);
307
308 DueTime.QuadPart = -5000 * 10000; // Timeout 5 sec.
309
310 KeSetTimer(&HubTimeoutContext->UrbTimeoutTimer,
311 DueTime,
312 &HubTimeoutContext->UrbTimeoutDPC);
313
316 HubTimeoutContext,
317 TRUE,
318 TRUE,
319 TRUE);
320
321 IsWaitTimeout = TRUE;
322 }
323
325
326 if (Status == STATUS_PENDING)
327 {
329 Suspended,
331 FALSE,
332 NULL);
333 }
334 else
335 {
337 }
338
339 if (IsWaitTimeout)
340 {
341 KeWaitForSingleObject(&HubTimeoutContext->UrbTimeoutEvent,
342 Suspended,
344 FALSE,
345 NULL);
346
347 ExFreePoolWithTag(HubTimeoutContext, USB_HUB_TAG);
348 }
349
350 return IoStatusBlock.Status;
351}
352
354NTAPI
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
369NTAPI
371 IN PVOID TransferBuffer,
372 IN ULONG BufferLen,
373 IN BOOLEAN IsDeviceToHost,
377 IN USHORT RequestValue,
378 IN USHORT RequestIndex)
379{
382 PVOID Buffer = NULL;
385
386 DPRINT("USBH_Transact: ... \n");
387
388 if (BufferLen)
389 {
390 Length = ALIGN_DOWN_BY(BufferLen + sizeof(ULONG), sizeof(ULONG));
391
393
394 if (!Buffer)
395 {
397 }
398
400 }
401
405
406 if (!Urb)
407 {
408 if (Buffer)
409 {
411 }
412
414 }
415
417
418 if (IsDeviceToHost)
419 {
420 if (BufferLen)
421 {
422 RtlZeroMemory(TransferBuffer, BufferLen);
423 }
424
426 }
427 else
428 {
429 if (BufferLen)
430 {
432 }
433
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
442 Urb->TransferBuffer = BufferLen != 0 ? Buffer : NULL;
443 Urb->TransferBufferLength = BufferLen;
444 Urb->TransferBufferMDL = NULL;
445 Urb->UrbLink = NULL;
446
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 {
457 }
458
459 if (Buffer)
460 {
462 }
463
465
466 return Status;
467}
468
470NTAPI
472 IN USHORT Port)
473{
477 ULONG ResetRetry = 0;
479
480 DPRINT("USBH_SyncResetPort: Port - %x\n", Port);
481
482 InterlockedIncrement(&HubExtension->PendingRequestCount);
483
484 KeWaitForSingleObject(&HubExtension->HubPortSemaphore,
485 Executive,
487 FALSE,
488 NULL);
489
490 Status = USBH_SyncGetPortStatus(HubExtension,
491 Port,
492 &PortStatus,
494
495 if (NT_SUCCESS(Status) &&
496 (PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0))
497 {
499 goto Exit;
500 }
501
502 HubExtension->HubFlags |= USBHUB_FDO_FLAG_RESET_PORT_LOCK;
503
504 while (TRUE)
505 {
507
509
510 InterlockedExchangePointer((PVOID)&HubExtension->pResetPortEvent,
511 &Event);
512
513 RequestType.B = 0;
517
518 Status = USBH_Transact(HubExtension,
519 NULL,
520 0,
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
542 Suspended,
544 FALSE,
545 &Timeout);
546
547 if (Status != STATUS_TIMEOUT)
548 {
549 break;
550 }
551
552 Status = USBH_SyncGetPortStatus(HubExtension,
553 Port,
554 &PortStatus,
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
568 goto Exit;
569 }
570
571 ResetRetry++;
572 }
573
574 Status = USBH_SyncGetPortStatus(HubExtension,
575 Port,
576 &PortStatus,
578
579 if ((PortStatus.PortStatus.Usb20PortStatus.CurrentConnectStatus == 0) &&
581 HubExtension->HubFlags & USBHUB_FDO_FLAG_USB20_HUB)
582 {
584 }
585
586 USBH_Wait(10);
587 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_RESET_PORT_LOCK;
588
589Exit:
590
591 KeReleaseSemaphore(&HubExtension->HubPortSemaphore,
593 1,
594 FALSE);
595
596 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
597 {
598 KeSetEvent(&HubExtension->PendingRequestEvent,
600 FALSE);
601 }
602
603 return Status;
604}
605
607NTAPI
610 OUT USB_DEVICE_TYPE * OutDeviceType)
611{
616 ULONG dummy;
618
619 DPRINT("USBH_GetDeviceType: ... \n");
620
621 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
622
624 {
625 DPRINT1("USBH_GetDeviceType: no QueryDeviceInformation()\n");
627 }
628
630
631 while (TRUE)
632 {
636
637 if (!DeviceInfo)
638 {
639 DPRINT1("USBH_GetDeviceType: ExAllocatePoolWithTag() failed\n");
641 break;
642 }
643
645
646 DeviceInfo->InformationLevel = 0;
647
648 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
652 &dummy);
653
655 {
656 if (NT_SUCCESS(Status))
657 {
658 DeviceType = DeviceInfo->DeviceType;
659 }
660
662 break;
663 }
664
667 }
668
669 if (OutDeviceType)
670 {
671 *OutDeviceType = DeviceType;
672 DPRINT("USBH_GetDeviceType: DeviceType - %x\n", DeviceType);
673 }
674
675 return Status;
676}
677
679NTAPI
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,
694 &dummy);
695}
696
698NTAPI
700{
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
727NTAPI
729 IN OUT PDEVICE_OBJECT * OutPdo1,
730 IN OUT PDEVICE_OBJECT * OutPdo2)
731{
734 PIRP Irp;
735 PIO_STACK_LOCATION IoStack;
737
738 DPRINT("USBH_SyncGetRootHubPdo: ... \n");
739
741
744 NULL,
745 0,
746 NULL,
747 0,
748 TRUE,
749 &Event,
751
752 if (!Irp)
753 {
755 }
756
758 IoStack->Parameters.Others.Argument1 = OutPdo1;
759 IoStack->Parameters.Others.Argument2 = OutPdo2;
760
762
763 if (Status == STATUS_PENDING)
764 {
766 Suspended,
768 FALSE,
769 NULL);
770 }
771 else
772 {
774 }
775
776 return IoStatusBlock.Status;
777}
778
780NTAPI
782 IN OUT PULONG OutHubCount)
783{
786 PIRP Irp;
787 PIO_STACK_LOCATION IoStack;
789
790 DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount);
791
793
796 NULL,
797 0,
798 NULL,
799 0,
800 TRUE,
801 &Event,
803
804 if (!Irp)
805 {
807 }
808
810 IoStack->Parameters.Others.Argument1 = OutHubCount;
811
813
814 if (Status == STATUS_PENDING)
815 {
817 Suspended,
819 FALSE,
820 NULL);
821 }
822 else
823 {
825 }
826
827 return IoStatusBlock.Status;
828}
829
831NTAPI
833{
834 PIRP Irp;
838 PIO_STACK_LOCATION IoStack;
839
840 DPRINT("USBH_SyncGetDeviceHandle: ... \n");
841
843
844 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
846 NULL,
847 0,
848 NULL,
849 0,
850 TRUE,
851 &Event,
853
854 if (!Irp)
855 {
856 DPRINT1("USBH_SyncGetDeviceHandle: Irp - NULL!\n");
857 return NULL;
858 }
859
861 IoStack->Parameters.Others.Argument1 = &DeviceHandle;
862
864 {
866 Suspended,
868 FALSE,
869 NULL);
870 }
871
872 return DeviceHandle;
873}
874
876NTAPI
878 IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor)
879{
882
883 DPRINT("USBH_GetDeviceDescriptor: ... \n");
884
886 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
888
889 if (!Urb)
890 {
891 DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n");
893 }
894
896
898 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
899
901 Urb->TransferBuffer = HubDeviceDescriptor;
903
905
907
908 return Status;
909}
910
912NTAPI
916 IN PULONG OutLength)
917{
918 PCOMMON_DEVICE_EXTENSION DeviceExtension;
921
922 DPRINT("USBH_SyncGetDeviceConfigurationDescriptor: ... \n");
923
924 DeviceExtension = DeviceObject->DeviceExtension;
925
926 if (OutLength)
927 {
928 *OutLength = 0;
929 }
930
932 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
934
935 if (!Urb)
936 {
938 }
939
941
943 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
944
948
949 if (DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_HUB ||
950 DeviceExtension->ExtensionType == USBH_EXTENSION_TYPE_PARENT)
951 {
953 }
954 else
955 {
957 }
958
959 if (OutLength)
960 {
961 *OutLength = Urb->TransferBufferLength;
962 }
963
964 if (Urb)
965 {
967 }
968
969 return Status;
970}
971
973NTAPI
975 IN PUSB_CONFIGURATION_DESCRIPTOR * OutDescriptor)
976{
978 ULONG ReturnedLen;
979 SIZE_T DescriptorLen;
981
982 DPRINT("USBH_GetConfigurationDescriptor: ... \n");
983
984 DescriptorLen = MAXUCHAR;
985
986 while (TRUE)
987 {
989 DescriptorLen,
991
992 if (!ConfigDescriptor)
993 {
995 break;
996 }
997
1000 DescriptorLen,
1001 &ReturnedLen);
1002
1003 if (ReturnedLen < sizeof(USB_CONFIGURATION_DESCRIPTOR))
1004 {
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
1023 *OutDescriptor = NULL;
1024 }
1025
1026 if (NT_SUCCESS(Status))
1027 {
1028 if (ReturnedLen < ConfigDescriptor->wTotalLength)
1029 {
1031 }
1032 }
1033 else
1034 {
1035 if (ConfigDescriptor)
1036 {
1038 }
1039
1040 *OutDescriptor = NULL;
1041 }
1042
1043 return Status;
1044}
1045
1047NTAPI
1049{
1050 PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo;
1051 ULONG NumberPorts;
1052 PUSBHUB_PORT_DATA PortData;
1053 USHORT RequestValue;
1056 PUSB_HUB_DESCRIPTOR HubDescriptor = NULL;
1057 ULONG ix;
1058 ULONG Retry;
1059
1060 DPRINT("USBH_SyncGetHubDescriptor: ... \n");
1061
1062 ExtendedHubInfo = ExAllocatePoolWithTag(NonPagedPool,
1064 USB_HUB_TAG);
1065
1066 if (!ExtendedHubInfo)
1067 {
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
1083
1084 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1086 USB_HUB_TAG);
1087
1088 if (!HubDescriptor)
1089 {
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 {
1104
1105 RequestType.B = 0;
1106 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1109
1110 Status = USBH_Transact(HubExtension,
1111 HubDescriptor,
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 {
1141 HubDescriptor = NULL;
1142 goto ErrorExit;
1143 }
1144
1145 HubDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1147 USB_HUB_TAG);
1148
1149 if (!HubDescriptor)
1150 {
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 {
1192 NumberPorts * sizeof(USBHUB_PORT_DATA),
1193 USB_HUB_TAG);
1194 }
1195
1196 if (!PortData)
1197 {
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
1231ErrorExit:
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
1247NTAPI
1249 IN UCHAR Index,
1253 IN PULONG OutLength,
1254 IN BOOLEAN IsValidateLength)
1255{
1257 ULONG TransferedLength;
1259
1260 DPRINT("USBH_SyncGetStringDescriptor: Index - %x, LanguageId - %x\n",
1261 Index,
1262 LanguageId);
1263
1265 sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1266 USB_HUB_TAG);
1267
1268 if (!Urb)
1269 {
1271 }
1272
1274
1276 Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
1277
1280
1281 Urb->Index = Index;
1283 Urb->LanguageId = LanguageId;
1284
1286
1287 if (!NT_SUCCESS(Status))
1288 {
1290 return Status;
1291 }
1292
1293 TransferedLength = Urb->TransferBufferLength;
1294
1295 if (TransferedLength > NumberOfBytes)
1296 {
1298 }
1299
1300 if (!NT_SUCCESS(Status))
1301 {
1303 return Status;
1304 }
1305
1306 if (OutLength)
1307 {
1308 *OutLength = TransferedLength;
1309 }
1310
1311 if (IsValidateLength && TransferedLength != Descriptor->bLength)
1312 {
1314 }
1315
1317
1318 return Status;
1319}
1320
1322NTAPI
1324 IN PUSHORT OutStatus,
1326 IN USHORT RequestIndex)
1327{
1329 NTSTATUS NtStatus;
1330 USHORT UsbStatus;
1331
1332 DPRINT("USBH_SyncGetStatus: ... \n");
1333
1335 sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST),
1336 USB_HUB_TAG);
1337
1338 if (!Urb)
1339 {
1341 }
1342
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
1357
1358 return NtStatus;
1359}
1360
1362NTAPI
1365 IN ULONG Length)
1366{
1368
1369 DPRINT("USBH_SyncGetHubStatus\n");
1370
1371 RequestType.B = 0;
1372 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1375
1376 return USBH_Transact(HubExtension,
1377 HubStatus,
1378 Length,
1383 0,
1384 0);
1385}
1386
1388NTAPI
1390 IN USHORT RequestValue)
1391{
1393
1394 DPRINT("USBH_SyncClearHubStatus: RequestValue - %x\n", RequestValue);
1395
1396 RequestType.B = 0;
1397 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1400
1401 return USBH_Transact(HubExtension,
1402 NULL,
1403 0,
1408 RequestValue,
1409 0);
1410}
1411
1413NTAPI
1415 IN USHORT Port,
1417 IN ULONG Length)
1418{
1420
1421 DPRINT("USBH_SyncGetPortStatus: Port - %x\n", Port);
1422
1423 RequestType.B = 0;
1424 RequestType.Recipient = BMREQUEST_TO_OTHER;
1427
1428 return USBH_Transact(HubExtension,
1429 PortStatus,
1430 Length,
1435 0,
1436 Port);
1437}
1438
1439
1441NTAPI
1443 IN USHORT Port,
1444 IN USHORT RequestValue)
1445{
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;
1456
1457 return USBH_Transact(HubExtension,
1458 NULL,
1459 0,
1464 RequestValue,
1465 Port);
1466}
1467
1469NTAPI
1471 IN USHORT Port,
1472 IN BOOLEAN IsWait)
1473{
1474 PUSBHUB_PORT_DATA PortData;
1475 PUSB_HUB_DESCRIPTOR HubDescriptor;
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;
1495
1496 Status = USBH_Transact(HubExtension,
1497 NULL,
1498 0,
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
1521NTAPI
1523{
1524 PUSB_HUB_DESCRIPTOR HubDescriptor;
1526 USHORT Port;
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
1552NTAPI
1554 IN USHORT Port)
1555{
1556 PUSBHUB_PORT_DATA PortData;
1559
1560 DPRINT("USBH_SyncDisablePort ... \n");
1561
1562 PortData = &HubExtension->PortData[Port - 1];
1563
1564 RequestType.B = 0;
1565 RequestType.Recipient = BMREQUEST_TO_DEVICE;
1568
1569 Status = USBH_Transact(HubExtension,
1570 NULL,
1571 0,
1577 Port);
1578
1579 if (NT_SUCCESS(Status))
1580 {
1582 }
1583
1584 return Status;
1585}
1586
1587BOOLEAN
1588NTAPI
1590 IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor)
1591{
1593 USHORT UsbStatus;
1595
1596 DPRINT("USBH_HubIsBusPowered: ... \n");
1597
1599 &UsbStatus,
1601 0);
1602
1603 if (!NT_SUCCESS(Status))
1604 {
1605 Result = (HubConfigDescriptor->bmAttributes & USB_CONFIG_POWERED_MASK)
1607 }
1608 else
1609 {
1610 Result = (UsbStatus & USB_GETSTATUS_SELF_POWERED) == 0;
1611 }
1612
1613 return Result;
1614}
1615
1617NTAPI
1619 IN PIRP Irp,
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
1636 NULL);
1637
1638 if (Event)
1639 {
1641 }
1642
1643 USBH_SubmitStatusChangeTransfer(HubExtension);
1644
1645 if (!InterlockedDecrement(&HubExtension->ResetRequestCount))
1646 {
1647 KeSetEvent(&HubExtension->ResetEvent,
1649 FALSE);
1650 }
1651
1653}
1654
1656NTAPI
1658 IN PIRP Irp,
1660 IN USHORT Port,
1661 IN USHORT RequestValue)
1662{
1663 PIO_STACK_LOCATION IoStack;
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;
1682
1683 Urb->RequestTypeReservedBits = RequestType.B;
1684 Urb->Request = USB_REQUEST_CLEAR_FEATURE;
1685 Urb->Index = Port;
1686 Urb->Value = RequestValue;
1687
1689 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1690 HubExtension->LowerDevice->StackSize);
1691
1692 IoStack = IoGetNextIrpStackLocation(Irp);
1693
1695 IoStack->Parameters.Others.Argument1 = Urb;
1697
1700 HubExtension,
1701 TRUE,
1702 TRUE,
1703 TRUE);
1704
1705 return IoCallDriver(HubExtension->LowerDevice, Irp);
1706}
1707
1709NTAPI
1711 IN PIRP Irp,
1713{
1714 PUSBHUB_FDO_EXTENSION HubExtension;
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)) &&
1727 {
1728 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
1729 {
1730 KeSetEvent(&HubExtension->PendingRequestEvent,
1732 FALSE);
1733 }
1734
1735 USBH_FreeWorkItem(HubExtension->WorkItemToQueue);
1736
1737 HubExtension->WorkItemToQueue = NULL;
1738
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
1765}
1766
1768NTAPI
1770 IN PIRP Irp,
1772 IN USHORT Port)
1773{
1776 PIO_STACK_LOCATION IoStack;
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
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;
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
1818 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1819 HubExtension->LowerDevice->StackSize);
1820
1821 IoStack = IoGetNextIrpStackLocation(Irp);
1822
1824 IoStack->Parameters.Others.Argument1 = Urb;
1826
1829 HubExtension,
1830 TRUE,
1831 TRUE,
1832 TRUE);
1833
1834 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
1835
1836 return Status;
1837}
1838
1839VOID
1840NTAPI
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,
1855 }
1856 else if (HubStatusChange.OverCurrentChange)
1857 {
1858 USBH_SyncClearHubStatus(HubExtension,
1860 if (HubStatus->HubStatus.OverCurrent)
1861 {
1862 DPRINT1("USBH_ProcessHubStateChange: OverCurrent UNIMPLEMENTED. FIXME\n");
1863 DbgBreakPoint();
1864 }
1865 }
1866}
1867
1868VOID
1869NTAPI
1871 IN USHORT Port,
1873{
1874 PUSBHUB_PORT_DATA PortData;
1875 USB_20_PORT_CHANGE PortStatusChange;
1876 PDEVICE_OBJECT PortDevice;
1877 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
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,
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
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;
1926
1927 HubExtension->HubFlags |= USBHUB_FDO_FLAG_STATE_CHANGING;
1928
1929 InsertTailList(&HubExtension->PdoList, &PortExtension->PortLink);
1930
1931 KeReleaseSpinLock(&HubExtension->RelationsWorkerSpinLock, Irql);
1932
1934 NULL);
1935
1936 if (SerialNumber)
1937 {
1939 }
1940
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
1978NTAPI
1981{
1982 PIRP Irp;
1983 PIO_STACK_LOCATION IoStack;
1985 KEVENT Event;
1987
1988 DPRINT("USBH_GetPortStatus ... \n");
1989
1990 *PortStatus = 0;
1991
1993
1995 HubExtension->LowerDevice,
1996 NULL,
1997 0,
1998 NULL,
1999 0,
2000 TRUE,
2001 &Event,
2002 &IoStatusBlock);
2003
2004 if (!Irp)
2005 {
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 {
2017 Suspended,
2018 KernelMode,
2019 FALSE,
2020 NULL);
2021 }
2022 else
2023 {
2025 }
2026
2027 return IoStatusBlock.Status;
2028}
2029
2031NTAPI
2033{
2034 PIRP Irp;
2036 KEVENT Event;
2038
2039 DPRINT("USBH_EnableParentPort ... \n");
2040
2042
2044 HubExtension->LowerDevice,
2045 NULL,
2046 0,
2047 NULL,
2048 0,
2049 TRUE,
2050 &Event,
2051 &IoStatusBlock);
2052
2053 if (!Irp)
2054 {
2056 }
2057
2058 Status = IoCallDriver(HubExtension->LowerDevice, Irp);
2059
2060 if (Status == STATUS_PENDING)
2061 {
2063 Suspended,
2064 KernelMode,
2065 FALSE,
2066 NULL);
2067 }
2068 else
2069 {
2071 }
2072
2073 return IoStatusBlock.Status;
2074}
2075
2077NTAPI
2079{
2080 struct _URB_PIPE_REQUEST * Urb;
2082
2083 DPRINT("USBH_ResetInterruptPipe ... \n");
2084
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);
2095 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2096
2097 Status = USBH_FdoSyncSubmitUrb(HubExtension->Common.SelfDevice,
2098 (PURB)Urb);
2099
2101 }
2102 else
2103 {
2105 }
2106
2107 if (NT_SUCCESS(Status))
2108 {
2109 HubExtension->RequestErrors = 0;
2110 }
2111
2112 return Status;
2113}
2114
2116NTAPI
2118{
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
2144VOID
2145NTAPI
2148{
2149 PUSBHUB_FDO_EXTENSION LowerHubExtension;
2150 PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension;
2153 USB_HUB_STATUS_AND_CHANGE HubStatus;
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,
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,
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,
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
2230Enum:
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
2290Exit:
2291
2292 KeReleaseSemaphore(&HubExtension->HubSemaphore,
2294 1,
2295 FALSE);
2296
2297 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2298 {
2299 KeSetEvent(&HubExtension->PendingRequestEvent,
2301 FALSE);
2302 }
2303
2304 if (!InterlockedDecrement((PLONG)&HubExtension->ResetRequestCount))
2305 {
2306 KeSetEvent(&HubExtension->ResetEvent,
2308 FALSE);
2309
2310 if (HubExtension->HubFlags & USBHUB_FDO_FLAG_DEFER_CHECK_IDLE)
2311 {
2312 USBH_CheckHubIdle(HubExtension);
2313 }
2314 }
2315}
2316
2318NTAPI
2320 IN PIRP Irp,
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;
2331 PVOID Bitmap;
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,
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
2363 }
2364
2365 DPRINT_SCE("USBH_ChangeIndication: HubExtension->RequestErrors - %x\n",
2366 HubExtension->RequestErrors);
2367 }
2368 else
2369 {
2370 HubExtension->RequestErrors = 0;
2371 }
2372
2374 HubExtension->SCEBitmapLength;
2375
2376 Status = USBH_AllocateWorkItem(HubExtension,
2377 &HubWorkItem,
2380 (PVOID *)&HubWorkItemBuffer,
2382
2383 if (!NT_SUCCESS(Status))
2384 {
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
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
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
2438}
2439
2441NTAPI
2443{
2444 PIRP Irp;
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
2460 }
2461
2462 Irp = HubExtension->SCEIrp;
2463
2464 if (!Irp)
2465 {
2467 }
2468
2469 Urb = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *)&HubExtension->SCEWorkerUrb;
2470
2471 Urb->Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
2473 Urb->Hdr.UsbdDeviceHandle = NULL;
2474
2475 Urb->PipeHandle = HubExtension->PipeInfo.PipeHandle;
2477 Urb->TransferBuffer = HubExtension->SCEBitmap;
2478 Urb->TransferBufferLength = HubExtension->SCEBitmapLength;
2479 Urb->TransferBufferMDL = NULL;
2480 Urb->UrbLink = NULL;
2481
2483 IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
2484 HubExtension->LowerDevice->StackSize);
2485
2486 IoStack = IoGetNextIrpStackLocation(Irp);
2487
2489 IoStack->Parameters.Others.Argument1 = &HubExtension->SCEWorkerUrb;
2491
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
2507NTAPI
2509 IN PUSB_DEVICE_HANDLE * OutDeviceHandle,
2510 IN USB_PORT_STATUS UsbPortStatus,
2511 IN USHORT Port)
2512{
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 {
2525 }
2526
2527 HubDeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
2528
2529 return CreateUsbDevice(HubExtension->BusInterface.BusContext,
2530 OutDeviceHandle,
2532 UsbPortStatus.AsUshort16,
2533 Port);
2534}
2535
2537NTAPI
2540 IN ULONG Flags)
2541{
2542 PUSB_BUSIFFN_REMOVE_USB_DEVICE RemoveUsbDevice;
2543
2544 DPRINT("USBD_RemoveDeviceEx: DeviceHandle - %p, Flags - %X\n",
2546 Flags);
2547
2548 RemoveUsbDevice = HubExtension->BusInterface.RemoveUsbDevice;
2549
2550 if (!RemoveUsbDevice)
2551 {
2553 }
2554
2555 return RemoveUsbDevice(HubExtension->BusInterface.BusContext,
2557 Flags);
2558}
2559
2561NTAPI
2568{
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 {
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,
2597}
2598
2599VOID
2600NTAPI
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,
2618 UsbDevicePdo);
2619}
2620
2621VOID
2622NTAPI
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
2638NTAPI
2640 IN PUSBHUB_FDO_EXTENSION HubExtension,
2641 IN PUSB_NODE_CONNECTION_INFORMATION_EX Info,
2642 IN ULONG Length,
2644{
2647 SIZE_T DeviceInfoLength;
2648 PUSB_NODE_CONNECTION_INFORMATION_EX NodeInfo;
2649 SIZE_T NodeInfoLength;
2650 ULONG PipeNumber;
2651 ULONG dummy;
2653
2654 DPRINT("USBD_GetDeviceInformationEx ... \n");
2655
2656 QueryDeviceInformation = HubExtension->BusInterface.QueryDeviceInformation;
2657
2659 {
2661 return Status;
2662 }
2663
2664 DeviceInfoLength = sizeof(USB_DEVICE_INFORMATION_0);
2665
2666 while (TRUE)
2667 {
2669 DeviceInfoLength,
2670 USB_HUB_TAG);
2671
2672 if (!DeviceInfo)
2673 {
2675 }
2676
2677 RtlZeroMemory(DeviceInfo, DeviceInfoLength);
2678
2679 DeviceInfo->InformationLevel = 0;
2680
2681 Status = QueryDeviceInformation(HubExtension->BusInterface.BusContext,
2683 DeviceInfo,
2684 DeviceInfoLength,
2685 &dummy);
2686
2688 {
2689 break;
2690 }
2691
2692 DeviceInfoLength = DeviceInfo->ActualLength;
2693
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 {
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
2739
2740 if (NodeInfo)
2741 {
2742 if (NodeInfoLength <= Length)
2743 {
2744 Length = NodeInfoLength;
2745 }
2746 else
2747 {
2749 }
2750
2751 RtlCopyMemory(Info, NodeInfo, Length);
2752
2753 ExFreePoolWithTag(NodeInfo, USB_HUB_TAG);
2754 }
2755
2756 return Status;
2757}
2758
2760NTAPI
2764{
2765 PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice;
2767
2768 DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n",
2769 HubExtension,
2772
2773 RestoreUsbDevice = HubExtension->BusInterface.RestoreUsbDevice;
2774
2775 if (RestoreUsbDevice)
2776 {
2777 Status = RestoreUsbDevice(HubExtension->BusInterface.BusContext,
2780 }
2781 else
2782 {
2784 }
2785
2786 return Status;
2787}
2788
2790NTAPI
2792 PUSBHUB_IO_WORK_ITEM * OutHubIoWorkItem,
2795 PVOID * OutHubWorkItemBuffer,
2797{
2798 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2800 PVOID WorkItemBuffer;
2801
2802 DPRINT("USBH_AllocateWorkItem: ... \n");
2803
2804 if (!(HubExtension->HubFlags & USBHUB_FDO_FLAG_WITEM_INIT))
2805 {
2807 }
2808
2809 HubIoWorkItem = ExAllocatePoolWithTag(NonPagedPool,
2810 sizeof(USBHUB_IO_WORK_ITEM),
2811 USB_HUB_TAG);
2812
2813 if (!HubIoWorkItem)
2814 {
2816 }
2817
2818 RtlZeroMemory(HubIoWorkItem, sizeof(USBHUB_IO_WORK_ITEM));
2819
2821
2822 HubIoWorkItem->HubWorkItem = WorkItem;
2823
2824 if (!WorkItem)
2825 {
2826 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2828 }
2829
2830 if (BufferLength && OutHubWorkItemBuffer)
2831 {
2832 WorkItemBuffer = ExAllocatePoolWithTag(NonPagedPool,
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
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
2870VOID
2871NTAPI
2874{
2875 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
2876 PUSBHUB_FDO_EXTENSION HubExtension;
2877 KIRQL OldIrql;
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);
2895
2896 if (HubIoWorkItem->HubWorkItemBuffer)
2897 {
2899 }
2900
2901 ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2902
2903 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2904 {
2905 KeSetEvent(&HubExtension->PendingRequestEvent,
2907 FALSE);
2908 }
2909
2911
2912 DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context);
2913}
2914
2915VOID
2916NTAPI
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,
2931 HubIoWorkItem->HubWorkItemType,
2932 HubIoWorkItem);
2933}
2934
2935VOID
2936NTAPI
2938{
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
2953}
2954
2955VOID
2956NTAPI
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 |
2969
2970 USBH_SubmitStatusChangeTransfer(HubExtension);
2971
2973 }
2974 else
2975 {
2977 }
2978
2979 KeSetEvent(&HubExtension->RootHubNotificationEvent,
2981 FALSE);
2982}
2983
2985NTAPI
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 {
2997 }
2998
2999 KeClearEvent(&HubExtension->RootHubNotificationEvent);
3000
3001 return RootHubInitNotification(HubExtension->BusInterface.BusContext,
3002 HubExtension,
3004}
3005
3007NTAPI
3009{
3010 PUSB_BUSIFFN_ROOTHUB_INIT_NOTIFY RootHubInitNotification;
3012
3013 DPRINT("USBD_UnRegisterRootHubCallBack ... \n");
3014
3015 RootHubInitNotification = HubExtension->BusInterface.RootHubInitNotification;
3016
3017 if (!RootHubInitNotification)
3018 {
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
3038VOID
3039NTAPI
3045{
3046 DPRINT("USBH_HubSetDWakeCompletion: ... \n");
3048}
3049
3050VOID
3051NTAPI
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
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
3101
3102 if (HubIdleIrp)
3103 {
3104 USBH_HubCancelIdleIrp(HubExtension, HubIdleIrp);
3105 }
3106}
3107
3108VOID
3109NTAPI
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
3123VOID
3124NTAPI
3126{
3127 PDEVICE_OBJECT PortDevice;
3128 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
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 {
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,
3172 1,
3173 FALSE);
3174
3175 if (!InterlockedDecrement((PLONG)&HubExtension->PendingRequestCount))
3176 {
3177 KeSetEvent(&HubExtension->PendingRequestEvent,
3179 FALSE);
3180 }
3181}
3182
3183VOID
3184NTAPI
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
3197 &IdleList,
3198 NtStatus);
3199
3200 USBH_FlushPortPwrList(HubExtension);
3201 }
3202}
3203
3204VOID
3205NTAPI
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
3219BOOLEAN
3220NTAPI
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;
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
3280Wait:
3281
3282 if (IsWait == TRUE)
3283 {
3284 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3286 1,
3287 FALSE);
3288 }
3289
3290 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3291 {
3292 KeSetEvent(&HubExtension->PendingRequestEvent,
3294 FALSE);
3295 }
3296
3297 return Result;
3298}
3299
3300VOID
3301NTAPI
3307{
3308 DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n");
3309}
3310
3312NTAPI
3314{
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,
3330 PowerState,
3332 HubExtension,
3333 &Irp);
3334
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,
3354 FALSE);
3355 }
3356 }
3357
3359
3360 return Status;
3361}
3362
3363VOID
3364NTAPI
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;
3374 KEVENT Event;
3375 ULONG Port;
3376 PIO_STACK_LOCATION IoStack;
3377 PUSB_IDLE_CALLBACK_INFO CallbackInfo;
3378 BOOLEAN IsReady;
3379 KIRQL OldIrql;
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 |
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
3416
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
3493IdleHub:
3494
3497 1,
3498 FALSE);
3499
3500 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3501 {
3502 KeSetEvent(&HubExtension->PendingRequestEvent,
3504 FALSE);
3505 }
3506
3507 if (!IsReady ||
3509 {
3510 DPRINT1("USBH_FdoIdleNotificationCallback: HubFlags - %lX\n",
3511 HubExtension->HubFlags);
3512
3513 HubExtension->HubFlags &= ~(USBHUB_FDO_FLAG_DEVICE_SUSPENDED |
3515
3516 /* Aborting Idle for Hub */
3518
3519 if (HubExtension->PendingIdleIrp)
3520 {
3521 Irp = HubExtension->PendingIdleIrp;
3522 HubExtension->PendingIdleIrp = NULL;
3523 }
3524
3526
3527 if (Irp)
3528 {
3529 USBH_HubCancelIdleIrp(HubExtension, Irp);
3530 }
3531
3532 DbgBreakPoint();
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
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,
3558 PowerState,
3560 &Event,
3561 NULL);
3562
3563 if (Status == STATUS_PENDING)
3564 {
3566 Executive,
3567 KernelMode,
3568 FALSE,
3569 NULL);
3570 }
3571 }
3572}
3573
3574VOID
3575NTAPI
3578{
3579 PUSBHUB_IDLE_PORT_CONTEXT IdlePortContext;
3580 NTSTATUS NtStatus;
3582 BOOLEAN IsFlush = FALSE;
3583
3584 DPRINT("USBH_CompletePortIdleIrpsWorker ... \n");
3585
3586 IdlePortContext = Context;
3587 NtStatus = IdlePortContext->Status;
3588
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
3605VOID
3606NTAPI
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
3628NTAPI
3630 IN PIRP Irp,
3632{
3633 PUSBHUB_FDO_EXTENSION HubExtension;
3634 NTSTATUS NtStatus;
3635 PVOID IdleIrp;
3636 KIRQL Irql;
3638 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3639
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 {
3653 }
3654
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,
3678 (PVOID *)&HubWorkItemBuffer,
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,
3699 (PVOID *)&HubWorkItemBuffer,
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
3718}
3719
3721NTAPI
3723{
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 {
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 ||
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;
3763
3764 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3765 return Status;
3766 }
3767
3768 IoStack = IoGetNextIrpStackLocation(Irp);
3769
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
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 |
3788
3789 Status = IoCallDriver(HubExtension->LowerPDO, Irp);
3790
3792
3793 if (Status == STATUS_PENDING &&
3794 HubExtension->HubFlags & USBHUB_FDO_FLAG_WAIT_IDLE_REQUEST)
3795 {
3796 HubExtension->PendingIdleIrp = Irp;
3797 }
3798
3800
3801 KeSetEvent(&HubExtension->IdleEvent, EVENT_INCREMENT, FALSE);
3802
3803 return Status;
3804}
3805
3806VOID
3807NTAPI
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
3822return; //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 ||
3854 HubFlags & USBHUB_FDO_FLAG_DEVICE_FAILED ||
3856 HubFlags & USBHUB_FDO_FLAG_DEVICE_REMOVED ||
3857 HubFlags & USBHUB_FDO_FLAG_STATE_CHANGING ||
3858 HubFlags & USBHUB_FDO_FLAG_WAKEUP_START ||
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
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
3918
3919 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
3921 1,
3922 FALSE);
3923
3924 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3925 {
3926 KeSetEvent(&HubExtension->PendingRequestEvent,
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
3940Exit:
3941 KeAcquireSpinLock(&HubExtension->CheckIdleSpinLock, &Irql);
3942 HubExtension->HubFlags &= ~USBHUB_FDO_FLAG_CHECK_IDLE_LOCK;
3943 KeReleaseSpinLock(&HubExtension->CheckIdleSpinLock, Irql);
3944}
3945
3946VOID
3947NTAPI
3950{
3951 DPRINT("USBH_CheckIdleWorker: ... \n");
3952 USBH_CheckHubIdle(HubExtension);
3953}
3954
3955VOID
3956NTAPI
3958{
3959 PUSBHUB_IO_WORK_ITEM HubIoWorkItem;
3961
3962 DPRINT("USBH_CheckIdleDeferred: HubExtension - %p\n", HubExtension);
3963
3964 Status = USBH_AllocateWorkItem(HubExtension,
3965 &HubIoWorkItem,
3967 0,
3968 NULL,
3970
3971 DPRINT("USBH_CheckIdleDeferred: HubIoWorkItem - %p\n", HubIoWorkItem);
3972
3973 if (NT_SUCCESS(Status))
3974 {
3975 USBH_QueueWorkItem(HubExtension, HubIoWorkItem);
3976 }
3977}
3978
3979VOID
3980NTAPI
3982{
3983 PUSBHUB_FDO_EXTENSION HubExtension;
3984 ULONG State;
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 {
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
4055NTAPI
4057{
4061
4062 DPRINT("USBH_ProcessDeviceInformation ... \n");
4063
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,
4073
4074 if (!NT_SUCCESS(Status))
4075 {
4076 if (ConfigDescriptor)
4077 {
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);
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 {
4128 }
4129
4130 return Status;
4131 }
4132
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
4147 {
4148 PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_HUB_DEVICE |
4150 }
4151 }
4152 else
4153 {
4155 }
4156
4157 if (ConfigDescriptor)
4158 {
4160 }
4161
4162 return Status;
4163}
4164
4165BOOLEAN
4166NTAPI
4168 IN USHORT idVendor,
4169 IN USHORT idProduct,
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,
4203 SN_DescriptorLength);
4204
4205 if (NumberBytes == SN_DescriptorLength)
4206 {
4207 return FALSE;
4208 }
4209 }
4210 }
4211 }
4212 }
4213
4214 return TRUE;
4215}
4216
4217BOOLEAN
4218NTAPI
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
4241NTAPI
4243 IN USHORT LanguageId)
4244{
4247 ULONG NumSymbols;
4248 ULONG ix;
4249 PWCHAR pSymbol;
4250 ULONG Length;
4251
4252 DPRINT("USBH_CheckDeviceLanguage: LanguageId - 0x%04X\n", LanguageId);
4253
4256 USB_HUB_TAG);
4257
4258 if (!Descriptor)
4259 {
4261 }
4262
4264
4266 0,
4267 0,
4268 Descriptor,
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 {
4289 goto Exit;
4290 }
4291
4292 pSymbol++;
4293 }
4294
4296
4297Exit:
4299 return Status;
4300}
4301
4303NTAPI
4305 IN LPWSTR * OutSerialNumber,
4306 IN PUSHORT OutDescriptorLength,
4307 IN USHORT LanguageId,
4308 IN UCHAR Index)
4309{
4312 LPWSTR SerialNumberBuffer = NULL;
4313 UCHAR StringLength;
4314 UCHAR Length;
4315
4316 DPRINT("USBH_GetSerialNumberString: ... \n");
4317
4318 *OutSerialNumber = NULL;
4319 *OutDescriptorLength = 0;
4320
4323 USB_HUB_TAG);
4324
4325 if (!Descriptor)
4326 {
4328 }
4329
4331
4333
4334 if (!NT_SUCCESS(Status))
4335 {
4336 goto Exit;
4337 }
4338
4340 Index,
4341 LanguageId,
4342 Descriptor,
4344 NULL,
4345 TRUE);
4346
4347 if (!NT_SUCCESS(Status) ||
4348 Descriptor->bLength <= sizeof(USB_COMMON_DESCRIPTOR))
4349 {
4351 goto Exit;
4352 }
4353
4354 StringLength = Descriptor->bLength -
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
4372Exit:
4374 return Status;
4375}
4376
4378NTAPI
4380 IN USHORT Port,
4381 IN USB_PORT_STATUS UsbPortStatus,
4382 IN ULONG IsWait)
4383{
4384 ULONG PdoNumber = 0;
4385 WCHAR CharDeviceName[64];
4388 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4390 LPWSTR SerialNumberBuffer;
4391 BOOLEAN IsHsDevice;
4392 BOOLEAN IsLsDevice;
4393 BOOLEAN IgnoringHwSerial = FALSE;
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,
4412 &DeviceName,
4414 0,
4415 FALSE,
4416 &DeviceObject);
4417
4418 ++PdoNumber;
4419 }
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
4439 PortExtension->Common.SelfDevice = DeviceObject;
4440
4441 PortExtension->HubExtension = HubExtension;
4442 PortExtension->RootHubExtension = HubExtension;
4443
4444 PortExtension->PortNumber = Port;
4446 PortExtension->IgnoringHwSerial = FALSE;
4447
4449
4450 InitializeListHead(&PortExtension->PortPowerList);
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 {
4468 }
4469 }
4470 else
4471 {
4473 }
4474
4475 /* Initialize PortExtension->InstanceID */
4479
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,
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 {
4546
4548 &SerialNumberBuffer,
4549 &PortExtension->SN_DescriptorLength,
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
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
4586ErrorExit:
4587
4589
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
4606Exit:
4607
4608 ASSERT(Port > 0);
4609 HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4610 return Status;
4611}
4612
4614NTAPI
4616 IN USHORT Port,
4617 IN BOOLEAN IsKeepDeviceData,
4618 IN BOOLEAN IsWait)
4619{
4621 PUSBHUB_PORT_DATA PortData;
4622 PDEVICE_OBJECT PortDevice;
4623 PUSBHUB_PORT_PDO_EXTENSION PortExtension;
4625 PVOID Handle;
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,
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 {
4663
4664 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4666 1,
4667 FALSE);
4668
4669 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4670 {
4671 KeSetEvent(&HubExtension->PendingRequestEvent,
4673 FALSE);
4674 }
4675
4676 return Status;
4677 }
4678
4679 PortExtension = PortDevice->DeviceExtension;
4680 DeviceHandle = &PortExtension->DeviceHandle;
4681
4683 NULL);
4684
4685 if (OldDeviceHandle)
4686 {
4687 if (!(PortExtension->PortPdoFlags & USBHUB_PDO_FLAG_REMOVING_PORT_PDO))
4688 {
4689 Status = USBD_RemoveDeviceEx(HubExtension,
4691 IsKeepDeviceData);
4692
4694 }
4695 }
4696 else
4697 {
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,
4717
4718 if (!NT_SUCCESS(Status))
4719 {
4720 goto ErrorExit;
4721 }
4722
4723 Status = USBD_CreateDeviceEx(HubExtension,
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,
4758 *DeviceHandle);
4759
4760 if (!NT_SUCCESS(Status))
4761 {
4763
4764 USBD_RemoveDeviceEx(HubExtension, Handle, 0);
4765 USBH_SyncDisablePort(HubExtension, Port);
4766
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
4780ErrorExit:
4781
4784
4785 if (NewDeviceHandle)
4786 {
4787 Status = USBD_RemoveDeviceEx(HubExtension, NewDeviceHandle, 0);
4788 }
4789
4790Exit:
4791
4792 KeReleaseSemaphore(&HubExtension->ResetDeviceSemaphore,
4794 1,
4795 FALSE);
4796
4797 if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
4798 {
4799 KeSetEvent(&HubExtension->PendingRequestEvent,
4801 FALSE);
4802 }
4803
4804 return Status;
4805}
4806
4808NTAPI
4810 IN PIRP Irp)
4811{
4812 PIO_STACK_LOCATION IoStack;
4814 BOOLEAN ShouldCompleteIrp;
4817
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",
4829 break;
4830
4832 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
4833 DPRINT("USBH_PdoDispatch: IRP_MJ_DEVICE_CONTROL ControlCode - %x\n",
4834 ControlCode);
4835
4837 {
4840 break;
4841 }
4842
4844 {
4845 DPRINT1("USBH_PdoDispatch: IOCTL_KS_PROPERTY FIXME\n");
4846 DbgBreakPoint();
4849 break;
4850 }
4851
4852 Status = Irp->IoStatus.Status;
4854