ReactOS  0.4.14-dev-1332-g6db3d88
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 
22 NTAPI
23 USBH_Wait(IN ULONG Milliseconds)
24 {
26 
27  DPRINT("USBH_Wait: Milliseconds - %x\n", Milliseconds);
28  Interval.QuadPart = -10000LL * Milliseconds - ((ULONGLONG)KeQueryTimeIncrement() - 1);
30 }
31 
33 NTAPI
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 
61 VOID
62 NTAPI
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 
78 NTAPI
80  IN PIRP Irp)
81 {
82  DPRINT_PNP("USBH_PassIrp: DeviceObject - %p, Irp - %p\n",
84  Irp);
85 
87  return IoCallDriver(DeviceObject, Irp);
88 }
89 
91 NTAPI
93  IN PIRP Irp,
95 {
96  PUSBHUB_URB_TIMEOUT_CONTEXT HubTimeoutContext;
97  KIRQL OldIrql;
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 
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 
132 NTAPI
134 {
136 
137  DPRINT("PdoExt: DeviceObject - %p\n", DeviceObject);
138 
139  if (DeviceObject)
140  {
142  }
143  else
144  {
145  PdoExtension = NULL;
146  }
147 
149 }
150 
151 NTSTATUS
152 NTAPI
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 
182 VOID
183 NTAPI
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,
208  FALSE);
209 }
210 
211 NTSTATUS
212 NTAPI
215  IN PVOID Data,
216  IN ULONG DataSize,
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 
248 NTSTATUS
249 NTAPI
251  IN PURB Urb)
252 {
253  KEVENT Event;
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 
269  DeviceObject,
270  NULL,
271  0,
272  NULL,
273  0,
274  TRUE,
275  &Event,
276  &IoStatusBlock);
277 
278  if (!Irp)
279  {
281  }
282 
283  IoStack = IoGetNextIrpStackLocation(Irp);
284  IoStack->Parameters.Others.Argument1 = Urb;
285 
286  HubTimeoutContext = ExAllocatePoolWithTag(NonPagedPool,
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,
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,
330  KernelMode,
331  FALSE,
332  NULL);
333  }
334  else
335  {
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
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
371  IN PVOID TransferBuffer,
372  IN ULONG BufferLen,
373  IN BOOLEAN IsDeviceToHost,
375  IN BM_REQUEST_TYPE RequestType,
376  IN UCHAR Request,
377  IN USHORT RequestValue,
378  IN USHORT RequestIndex)
379 {
382  PVOID Buffer = NULL;
383  ULONG Length;
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 
404  USB_HUB_TAG);
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  {
431  RtlCopyMemory(Buffer, TransferBuffer, BufferLen);
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 
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  {
462  }
463 
465 
466  return Status;
467 }
468 
469 NTSTATUS
470 NTAPI
472  IN USHORT Port)
473 {
475  KEVENT Event;
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,
486  KernelMode,
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  {
506  BM_REQUEST_TYPE RequestType;
507 
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,
523  RequestType,
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,
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,
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) &&
580  NT_SUCCESS(Status) &&
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 
589 Exit:
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 
606 NTSTATUS
607 NTAPI
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");
626  return STATUS_NOT_IMPLEMENTED;
627  }
628 
630 
631  while (TRUE)
632  {
635  USB_HUB_TAG);
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,
649  DeviceHandle,
650  DeviceInfo,
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 
678 NTSTATUS
679 NTAPI
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 
698 NTAPI
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 
726 NTSTATUS
727 NTAPI
729  IN OUT PDEVICE_OBJECT * OutPdo1,
730  IN OUT PDEVICE_OBJECT * OutPdo2)
731 {
732  KEVENT Event;
734  PIRP Irp;
735  PIO_STACK_LOCATION IoStack;
737 
738  DPRINT("USBH_SyncGetRootHubPdo: ... \n");
739 
741 
743  DeviceObject,
744  NULL,
745  0,
746  NULL,
747  0,
748  TRUE,
749  &Event,
750  &IoStatusBlock);
751 
752  if (!Irp)
753  {
755  }
756 
757  IoStack = IoGetNextIrpStackLocation(Irp);
758  IoStack->Parameters.Others.Argument1 = OutPdo1;
759  IoStack->Parameters.Others.Argument2 = OutPdo2;
760 
762 
763  if (Status == STATUS_PENDING)
764  {
766  Suspended,
767  KernelMode,
768  FALSE,
769  NULL);
770  }
771  else
772  {
774  }
775 
776  return IoStatusBlock.Status;
777 }
778 
779 NTSTATUS
780 NTAPI
782  IN OUT PULONG OutHubCount)
783 {
784  KEVENT Event;
786  PIRP Irp;
787  PIO_STACK_LOCATION IoStack;
789 
790  DPRINT("USBH_SyncGetHubCount: *OutHubCount - %x\n", *OutHubCount);
791 
793 
795  DeviceObject,
796  NULL,
797  0,
798  NULL,
799  0,
800  TRUE,
801  &Event,
802  &IoStatusBlock);
803 
804  if (!Irp)
805  {
807  }
808 
809  IoStack = IoGetNextIrpStackLocation(Irp);
810  IoStack->Parameters.Others.Argument1 = OutHubCount;
811 
813 
814  if (Status == STATUS_PENDING)
815  {
817  Suspended,
818  KernelMode,
819  FALSE,
820  NULL);
821  }
822  else
823  {
825  }
826 
827  return IoStatusBlock.Status;
828 }
829 
831 NTAPI
833 {
834  PIRP Irp;
835  KEVENT Event;
838  PIO_STACK_LOCATION IoStack;
839 
840  DPRINT("USBH_SyncGetDeviceHandle: ... \n");
841 
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 
864  {
866  Suspended,
867  KernelMode,
868  FALSE,
869  NULL);
870  }
871 
872  return DeviceHandle;
873 }
874 
875 NTSTATUS
876 NTAPI
878  IN PUSB_DEVICE_DESCRIPTOR HubDeviceDescriptor)
879 {
880  struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
882 
883  DPRINT("USBH_GetDeviceDescriptor: ... \n");
884 
886  sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
887  USB_HUB_TAG);
888 
889  if (!Urb)
890  {
891  DPRINT1("USBH_SyncGetDeviceHandle: Urb - NULL!\n");
893  }
894 
895  RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
896 
898  Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
899 
901  Urb->TransferBuffer = HubDeviceDescriptor;
903 
905 
907 
908  return Status;
909 }
910 
911 NTSTATUS
912 NTAPI
914  IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
916  IN PULONG OutLength)
917 {
918  PCOMMON_DEVICE_EXTENSION DeviceExtension;
919  struct _URB_CONTROL_DESCRIPTOR_REQUEST * Urb;
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),
933  USB_HUB_TAG);
934 
935  if (!Urb)
936  {
938  }
939 
940  RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
941 
943  Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
944 
946  Urb->TransferBuffer = ConfigDescriptor;
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 
972 NTSTATUS
973 NTAPI
975  IN PUSB_CONFIGURATION_DESCRIPTOR * OutDescriptor)
976 {
977  PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
978  ULONG ReturnedLen;
979  SIZE_T DescriptorLen;
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  {
995  break;
996  }
997 
999  ConfigDescriptor,
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 
1022  ExFreePool(ConfigDescriptor);
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  {
1037  ExFreePool(ConfigDescriptor);
1038  }
1039 
1040  *OutDescriptor = NULL;
1041  }
1042 
1043  return Status;
1044 }
1045 
1046 NTSTATUS
1047 NTAPI
1049 {
1050  PUSB_EXTHUB_INFORMATION_0 ExtendedHubInfo;
1051  ULONG NumberPorts;
1052  PUSBHUB_PORT_DATA PortData;
1053  USHORT RequestValue;
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  {
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,
1085  NumberOfBytes,
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  {
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,
1115  RequestType,
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,
1146  NumberOfBytes,
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 
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
1249  IN UCHAR Index,
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 
1265  sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
1266  USB_HUB_TAG);
1267 
1268  if (!Urb)
1269  {
1271  }
1272 
1273  RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
1274 
1276  Urb->Hdr.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
1277 
1278  Urb->TransferBuffer = Descriptor;
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 
1321 NTSTATUS
1322 NTAPI
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 
1335  sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST),
1336  USB_HUB_TAG);
1337 
1338  if (!Urb)
1339  {
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 
1357 
1358  return NtStatus;
1359 }
1360 
1361 NTSTATUS
1362 NTAPI
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,
1381  RequestType,
1383  0,
1384  0);
1385 }
1386 
1387 NTSTATUS
1388 NTAPI
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,
1406  RequestType,
1408  RequestValue,
1409  0);
1410 }
1411 
1412 NTSTATUS
1413 NTAPI
1415  IN USHORT Port,
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,
1433  RequestType,
1435  0,
1436  Port);
1437 }
1438 
1439 
1440 NTSTATUS
1441 NTAPI
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,
1462  RequestType,
1464  RequestValue,
1465  Port);
1466 }
1467 
1468 NTSTATUS
1469 NTAPI
1471  IN USHORT Port,
1472  IN BOOLEAN IsWait)
1473 {
1474  PUSBHUB_PORT_DATA PortData;
1475  PUSB_HUB_DESCRIPTOR HubDescriptor;
1477  BM_REQUEST_TYPE RequestType;
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,
1501  RequestType,
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
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 
1551 NTSTATUS
1552 NTAPI
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,
1574  RequestType,
1577  Port);
1578 
1579  if (NT_SUCCESS(Status))
1580  {
1582  }
1583 
1584  return Status;
1585 }
1586 
1587 BOOLEAN
1588 NTAPI
1590  IN PUSB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor)
1591 {
1592  BOOLEAN Result;
1593  USHORT UsbStatus;
1594  NTSTATUS Status;
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 
1616 NTSTATUS
1617 NTAPI
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 
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 
1655 NTSTATUS
1656 NTAPI
1658  IN PIRP Irp,
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 
1689  IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1690  HubExtension->LowerDevice->StackSize);
1691 
1692  IoStack = IoGetNextIrpStackLocation(Irp);
1693 
1695  IoStack->Parameters.Others.Argument1 = Urb;
1696  IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1697 
1700  HubExtension,
1701  TRUE,
1702  TRUE,
1703  TRUE);
1704 
1705  return IoCallDriver(HubExtension->LowerDevice, Irp);
1706 }
1707 
1708 NTSTATUS
1709 NTAPI
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)) &&
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 
1767 NTSTATUS
1768 NTAPI
1770  IN PIRP Irp,
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 
1818  IoSizeOfIrp(HubExtension->LowerDevice->StackSize),
1819  HubExtension->LowerDevice->StackSize);
1820 
1821  IoStack = IoGetNextIrpStackLocation(Irp);
1822 
1824  IoStack->Parameters.Others.Argument1 = Urb;
1825  IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1826 
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
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,
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 
1868 VOID
1869 NTAPI
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 
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 
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 
1977 NTSTATUS
1978 NTAPI
1981 {
1982  PIRP Irp;
1983  PIO_STACK_LOCATION IoStack;
1984  NTSTATUS Status;
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 
2030 NTSTATUS
2031 NTAPI
2033 {
2034  PIRP Irp;
2035  NTSTATUS Status;
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 
2076 NTSTATUS
2077 NTAPI
2079 {
2080  struct _URB_PIPE_REQUEST * Urb;
2081  NTSTATUS Status;
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 
2115 NTSTATUS
2116 NTAPI
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
2147  IN PVOID Context)
2148 {
2149  PUSBHUB_FDO_EXTENSION LowerHubExtension;
2150  PUSBHUB_PORT_PDO_EXTENSION LowerPortExtension;
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,
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,
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,
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 
2317 NTSTATUS
2318 NTAPI
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;
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,
2379  BufferLength,
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 
2440 NTSTATUS
2441 NTAPI
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 
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;
2490  IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
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 
2506 NTSTATUS
2507 NTAPI
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  {
2524  return STATUS_NOT_IMPLEMENTED;
2525  }
2526 
2527  HubDeviceHandle = USBH_SyncGetDeviceHandle(HubExtension->LowerDevice);
2528 
2529  return CreateUsbDevice(HubExtension->BusInterface.BusContext,
2530  OutDeviceHandle,
2532  UsbPortStatus.AsUshort16,
2533  Port);
2534 }
2535 
2536 NTSTATUS
2537 NTAPI
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
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,
2597 }
2598 
2599 VOID
2600 NTAPI
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
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
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;
2652  NTSTATUS Status;
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,
2682  DeviceHandle,
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 
2759 NTSTATUS
2760 NTAPI
2764 {
2765  PUSB_BUSIFFN_RESTORE_DEVICE RestoreUsbDevice;
2766  NTSTATUS Status;
2767 
2768  DPRINT("USBD_RestoreDeviceEx: HubExtension - %p, OldDeviceHandle - %p, NewDeviceHandle - %p\n",
2769  HubExtension,
2771  NewDeviceHandle);
2772 
2773  RestoreUsbDevice = HubExtension->BusInterface.RestoreUsbDevice;
2774 
2775  if (RestoreUsbDevice)
2776  {
2777  Status = RestoreUsbDevice(HubExtension->BusInterface.BusContext,
2779  NewDeviceHandle);
2780  }
2781  else
2782  {
2784  }
2785 
2786  return Status;
2787 }
2788 
2789 NTSTATUS
2790 NTAPI
2792  PUSBHUB_IO_WORK_ITEM * OutHubIoWorkItem,
2795  PVOID * OutHubWorkItemBuffer,
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  {
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);
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 
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
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  {
2899  }
2900 
2901  ExFreePoolWithTag(HubIoWorkItem, USB_HUB_TAG);
2902 
2903  if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
2904  {
2905  KeSetEvent(&HubExtension->PendingRequestEvent,
2907  FALSE);
2908  }
2909 
2910  IoFreeWorkItem(WorkItem);
2911 
2912  DPRINT("USBH_Worker: HubIoWorkItem %p complete\n", Context);
2913 }
2914 
2915 VOID
2916 NTAPI
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
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
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  {
2976  HubExtension->HubFlags |= USBHUB_FDO_FLAG_DO_ENUMERATION;
2977  }
2978 
2979  KeSetEvent(&HubExtension->RootHubNotificationEvent,
2981  FALSE);
2982 }
2983 
2984 NTSTATUS
2985 NTAPI
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,
3004 }
3005 
3006 NTSTATUS
3007 NTAPI
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
3043  IN PVOID Context,
3045 {
3046  DPRINT("USBH_HubSetDWakeCompletion: ... \n");
3048 }
3049 
3050 VOID
3051 NTAPI
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 
3108 VOID
3109 NTAPI
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
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 
3183 VOID
3184 NTAPI
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 
3204 VOID
3205 NTAPI
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
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,
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 
3300 VOID
3301 NTAPI
3305  IN PVOID Context,
3307 {
3308  DPRINT("USBH_FdoWaitWakeIrpCompletion ... \n");
3309 }
3310 
3311 NTSTATUS
3312 NTAPI
3314 {
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,
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 
3363 VOID
3364 NTAPI
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;
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 |
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 
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 
3497  1,
3498  FALSE);
3499 
3500  if (!InterlockedDecrement(&HubExtension->PendingRequestCount))
3501  {
3502  KeSetEvent(&HubExtension->PendingRequestEvent,
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 |
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",
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 
3574 VOID
3575 NTAPI
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 
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
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
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 
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,
3677  sizeof(USBHUB_IDLE_PORT_CONTEXT),
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,
3698  sizeof(USBHUB_IDLE_HUB_CONTEXT),
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 
3720 NTSTATUS
3721 NTAPI
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  {
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;
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 
3806 VOID
3807 NTAPI
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 
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 
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
3949  IN PVOID Context)
3950 {
3951  DPRINT("USBH_CheckIdleWorker: ... \n");
3952  USBH_CheckHubIdle(HubExtension);
3953 }
3954 
3955 VOID
3956 NTAPI
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,
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 
3979 VOID
3980 NTAPI
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 
4054 NTSTATUS
4055 NTAPI
4057 {
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 
4147  {
4148  PortExtension->PortPdoFlags |= (USBHUB_PDO_FLAG_HUB_DEVICE |
4150  }
4151  }
4152  else
4153  {
4155  }
4156 
4157  if (ConfigDescriptor)
4158  {
4159  ExFreePool(ConfigDescriptor);
4160  }
4161 
4162  return Status;
4163 }
4164 
4165 BOOLEAN
4166 NTAPI
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,
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
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
4243  IN USHORT LanguageId)
4244 {
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 
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 
4297 Exit:
4299  return Status;
4300 }
4301 
4302 NTSTATUS
4303 NTAPI
4305  IN LPWSTR * OutSerialNumber,
4306  IN PUSHORT OutDescriptorLength,
4307  IN USHORT LanguageId,
4308  IN UCHAR Index)
4309 {
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 
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 
4372 Exit:
4374  return Status;
4375 }
4376 
4377 NTSTATUS
4378 NTAPI
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;
4394  NTSTATUS Status;
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,
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 
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);
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 */
4477  DestinationString.MaximumLength = 4 * sizeof(WCHAR);
4479 
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 
4547  USBH_GetSerialNumberString(PortExtension->Common.SelfDevice,
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 
4586 ErrorExit:
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 
4606 Exit:
4607 
4608  ASSERT(Port > 0);
4609  HubExtension->PortData[Port-1].DeviceObject = DeviceObject;
4610  return Status;
4611 }
4612 
4613 NTSTATUS
4614 NTAPI
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;
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,
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  {
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,
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,
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  {
4773  }
4774 
4775  goto Exit;
4776  }
4777 
4778  *DeviceHandle = NULL;
4779 
4780 ErrorExit:
4781 
4783  OldDeviceHandle);
4784 
4785  if (NewDeviceHandle)
4786  {
4787  Status = USBD_RemoveDeviceEx(HubExtension, NewDeviceHandle, 0);
4788  }
4789 
4790 Exit:
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 
4807 NTSTATUS
4808 NTAPI
4810  IN PIRP Irp)
4811 {
4812  PIO_STACK_LOCATION IoStack;
4813  UCHAR MajorFunction;
4814  BOOLEAN ShouldCompleteIrp;
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);
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 
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  break;
4855 
4857  Status = USBH_PdoInternalControl(PortExtension, Irp);
4858  break;
4859 
4860  case IRP_MJ_PNP:
4861  Status = USBH_PdoPnP(PortExtension,
4862  Irp,
4863  IoStack->MinorFunction,
4864  &ShouldCompleteIrp);
4865 
4866  if (ShouldCompleteIrp)
4867  {
4869  }
4870 
4871  break;
4872 
4873  case IRP_MJ_POWER:
4874  Status = USBH_PdoPower(PortExtension, Irp, IoStack->MinorFunction);
4875  break;
4876 
4877  case IRP_MJ_SYSTEM_CONTROL:
4878  DPRINT1("USBH_PdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n");
4879  //USBH_PortSystemControl(PortExtension, Irp);
4880  Status = Irp->IoStatus.Status;
4882  break;
4883 
4884  default:
4885  DPRINT("USBH_PdoDispatch: Unhandled MajorFunction - %d\n", MajorFunction);
4886  Status = Irp->IoStatus.Status;
4888  break;
4889  }
4890 
4891  return Status;
4892 }
4893 
4894 NTSTATUS
4895 NTAPI
4897  IN PIRP Irp)
4898 {
4899  PIO_STACK_LOCATION IoStack;
4900  UCHAR MajorFunction;
4901  NTSTATUS Status;
4902 
4903  IoStack = IoGetCurrentIrpStackLocation(Irp);
4904 
4905  DPRINT("USBH_FdoDispatch: HubExtension - %p, Irp - %p, MajorFunction - %X\n",
4906  HubExtension,
4907  Irp,
4908  IoStack->MajorFunction);
4909 
4910  MajorFunction = IoStack->MajorFunction;
4911 
4912  switch (MajorFunction)
4913  {
4914  case IRP_MJ_CREATE:
4915  case IRP_MJ_CLOSE:
4918  break;
4919 
4920  case IRP_MJ_DEVICE_CONTROL:
4921  Status = USBH_DeviceControl(HubExtension, Irp);
4922  break;
4923 
4924  case IRP_MJ_PNP:
4925  Status = USBH_FdoPnP(HubExtension, Irp, IoStack->MinorFunction);
4926  break;
4927 
4928  case IRP_MJ_POWER:
4929  Status = USBH_FdoPower(HubExtension, Irp, IoStack->MinorFunction);
4930  break;
4931 
4932  case IRP_MJ_SYSTEM_CONTROL:
4933  DPRINT1("USBH_FdoDispatch: USBH_SystemControl() UNIMPLEMENTED. FIXME\n");
4934  /* fall through */
4935 
4937  default:
4938  Status = USBH_PassIrp(HubExtension->LowerDevice, Irp);
4939  break;
4940  }
4941 
4942  return Status;
4943 }
4944 
4945 NTSTATUS
4946 NTAPI
4948  IN PDEVICE_OBJECT LowerPDO)
4949 {
4951  NTSTATUS Status;
4952  PUSBHUB_FDO_EXTENSION HubExtension;
4953  PDEVICE_OBJECT LowerDevice;
4954 
4955  DPRINT("USBH_AddDevice: DriverObject - %p, LowerPDO - %p\n",
4956  DriverObject,
4957  LowerPDO);
4958 
4959  DeviceObject = NULL;
4960 
4962  sizeof(USBHUB_FDO_EXTENSION),
4963  NULL,
4964  0x8600,
4966  FALSE,
4967  &DeviceObject);
4968 
4969  if (!NT_SUCCESS(Status))
4970  {
4971  DPRINT1("USBH_AddDevice: IoCreateDevice() fail\n");
4972 
4973  if (DeviceObject)
4974  {
4976  }
4977 
4978  return Status;
4979  }
4980 
4981  DPRINT("USBH_AddDevice: DeviceObject - %p\n", DeviceObject);
4982 
4983  HubExtension = DeviceObject->DeviceExtension;
4984  RtlZeroMemory(HubExtension, sizeof(USBHUB_FDO_EXTENSION));
4985 
4986  HubExtension->Common.ExtensionType = USBH_EXTENSION_TYPE_HUB;
4987 
4988  LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, LowerPDO);
4989 
4990  if (!LowerDevice)
4991  {
4992  DPRINT1("USBH_AddDevice: IoAttachDeviceToDeviceStack() fail\n");
4993 
4994  if (DeviceObject)
4995  {
4997  }
4998 
4999  return STATUS_UNSUCCESSFUL;
5000  }
5001 
5002  DPRINT("USBH_AddDevice: LowerDevice - %p\n", LowerDevice);
5003 
5004  HubExtension->Common.SelfDevice = DeviceObject;
5005 
5006  HubExtension->LowerPDO = LowerPDO;
5007  HubExtension->LowerDevice = LowerDevice;
5008 
5009  KeInitializeSemaphore(&HubExtension->IdleSemaphore, 1, 1);
5010 
5013 
5014  DPRINT("USBH_AddDevice: call IoWMIRegistrationControl() UNIMPLEMENTED. FIXME\n");
5015 
5016  return Status;
5017 }
5018 
5019 VOID
5020 NTAPI
5022 {
5023  DPRINT("USBH_DriverUnload: UNIMPLEMENTED\n");
5024 
5026  {
5029  }
5030 }
5031 
5032 NTSTATUS
5033 NTAPI
5035  IN PIRP Irp)
5036 {
5037  PCOMMON_DEVICE_EXTENSION DeviceExtension;
5038  ULONG ExtensionType;
5039  NTSTATUS Status;
5040 
5041 
5042  DeviceExtension = DeviceObject->DeviceExtension;
5043  ExtensionType = DeviceExtension->ExtensionType;
5044 
5045  if (ExtensionType == USBH_EXTENSION_TYPE_HUB)
5046  {
5047  DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n",
5048  DeviceObject,
5049  Irp);
5050 
5051  Status = USBH_FdoDispatch((PUSBHUB_FDO_EXTENSION)DeviceExtension, Irp);
5052  }
5053  else if (ExtensionType == USBH_EXTENSION_TYPE_PORT)
5054  {
5056  UCHAR MajorFunction = IoStack->MajorFunction;
5057  BOOLEAN IsDprint = TRUE;
5058 
5059  if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)
5060  {
5061  ULONG ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
5062 
5064  {
5065  IsDprint = FALSE;
5066  }
5067  }
5068 
5069  if (IsDprint)
5070  {
5071  DPRINT("USBH_HubDispatch: DeviceObject - %p, Irp - %p\n",
5072  DeviceObject,
5073  Irp);
5074  }
5075 
5077  }
5078  else
5079  {
5080  DPRINT1("USBH_HubDispatch: Unknown ExtensionType - %x\n", ExtensionType);
5081  DbgBreakPoint();
5083  }
5084 
5085  return Status;
5086 }
5087 
5088 NTSTATUS
5089 NTAPI
5091 {
5093 
5094  DPRINT("USBH_RegQueryGenericUSBDeviceString ... \n");
5095 
5097 
5100  QueryTable[0].Name = L"GenericUSBDeviceString";
5101  QueryTable[0].EntryContext = USBDeviceString;
5103  QueryTable[0].DefaultData = 0;
5104  QueryTable[0].DefaultLength = 0;
5105 
5107  L"usbflags",
5108  QueryTable,
5109  NULL,
5110  NULL);
5111 }
5112 
5113 NTSTATUS
5114 NTAPI
5117 {
5118  DPRINT("USBHUB: DriverEntry - %wZ\n", RegistryPath);
5119 
5122 
5125 
5128 
5132 
5134 
5135  return STATUS_SUCCESS;
5136 }
5137 
NTSTATUS NTAPI USBD_GetDeviceInformationEx(IN PUSBHUB_PORT_PDO_EXTENSION PortExtension, IN PUSBHUB_FDO_EXTENSION HubExtension, IN PUSB_NODE_CONNECTION_INFORMATION_EX Info, IN ULONG Length, IN PUSB_DEVICE_HANDLE DeviceHandle)
Definition: usbhub.c:2639
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
enum _USB_DEVICE_TYPE USB_DEVICE_TYPE
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
PUSBHUB_FDO_EXTENSION HubExtension
Definition: usbhub.h:137
NTSTATUS NTAPI USBH_HubDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: usbhub.c:5034
USB_20_PORT_STATUS Usb20PortStatus
Definition: usb200.h:223
VOID NTAPI USBH_UrbTimeoutDPC(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: usbhub.c:184
#define USBH_EXTENSION_TYPE_PARENT
Definition: usbhub.h:30
#define DO_POWER_PAGABLE
struct _USB_DEVICE_DESCRIPTOR USB_DEVICE_DESCRIPTOR
#define IOCTL_KS_PROPERTY
Definition: ks.h:127
CPPORT Port[4]
Definition: headless.c:34
VOID NTAPI USBH_HubQueuePortIdleIrps(IN PUSBHUB_FDO_EXTENSION HubExtension, IN PLIST_ENTRY IdleList)
Definition: usbhub.c:3052
const uint16_t * PCWSTR
Definition: typedefs.h:56
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4051
#define IN
Definition: typedefs.h:39
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:308
#define STATUS_DEVICE_REMOVED
Definition: ntstatus.h:795
UCHAR bDescriptorLength
Definition: usb100.h:171
PUSB_DEVICE_HANDLE DeviceHandle
Definition: usbhub.h:211
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSTATUS NTAPI USBH_FdoSubmitWaitWakeIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
Definition: usbhub.c:3313
_In_ UCHAR _In_ POWER_STATE PowerState
Definition: pofuncs.h:42
_Inout_ PUSB_DEVICE_HANDLE _Out_writes_bytes_to_ DeviceDescriptorBufferLength PUCHAR _Inout_ PULONG _Out_writes_bytes_to_ ConfigDescriptorBufferLength PUCHAR ConfigDescriptorBuffer
Definition: hubbusif.h:151
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define LL
Definition: tui.h:84
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI USBH_SyncGetRootHubPdo(IN PDEVICE_OBJECT DeviceObject, IN OUT PDEVICE_OBJECT *OutPdo1, IN OUT PDEVICE_OBJECT *OutPdo2)
Definition: usbhub.c:728
DEVICE_POWER_STATE DeviceWake
Definition: usbhub.h:159
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
#define USBHUB_FDO_FLAG_DEFER_CHECK_IDLE
Definition: usbhub.h:48
NTSTATUS NTAPI USBH_ChangeIndicationProcessChange(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: usbhub.c:1710
NTSTATUS NTAPI USBH_FdoSubmitIdleRequestIrp(IN PUSBHUB_FDO_EXTENSION HubExtension)
Definition: usbhub.c:3722
USB_BUSIFFN_REMOVE_USB_DEVICE * PUSB_BUSIFFN_REMOVE_USB_DEVICE
Definition: hubbusif.h:140
WORK_QUEUE_TYPE HubWorkItemType
Definition: usbhub.h:136
#define USBHUB_PDO_FLAG_REMOTE_WAKEUP
Definition: usbhub.h:65
#define USBHUB_FEATURE_C_PORT_ENABLE
Definition: usbhub.h:99
Type
Definition: Type.h:6
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
struct _Entry Entry
Definition: kefuncs.h:627
#define IOCTL_INTERNAL_USB_SUBMIT_URB
Definition: usbioctl.h:32
NTSTATUS NTAPI USBD_RemoveDeviceEx(IN PUSBHUB_FDO_EXTENSION HubExtension, IN PUSB_DEVICE_HANDLE DeviceHandle, IN ULONG Flags)
Definition: usbhub.c:2538
struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST SCEWorkerUrb
Definition: usbhub.h:175
#define USBHUB_PDO_FLAG_POWER_D1_OR_D2
Definition: usbhub.h:74
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
#define STATUS_NOT_IMPLEMENTED
Definition: