xref: /reactos/drivers/usb/usbport/device.c (revision 595b846d)
1 /*
2  * PROJECT:     ReactOS USB Port Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBPort device functions
5  * COPYRIGHT:   Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 #include "usbport.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 NTSTATUS
14 NTAPI
15 USBPORT_SendSetupPacket(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
16                         IN PDEVICE_OBJECT FdoDevice,
17                         IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
18                         IN PVOID Buffer,
19                         IN ULONG Length,
20                         IN OUT PULONG TransferedLen,
21                         IN OUT PUSBD_STATUS pUSBDStatus)
22 {
23     PURB Urb;
24     PMDL Mdl;
25     USBD_STATUS USBDStatus;
26     KEVENT Event;
27     NTSTATUS Status;
28 
29     DPRINT("USBPORT_SendSetupPacket: DeviceHandle - %p, FdoDevice - %p, SetupPacket - %p, Buffer - %p, Length - %x, TransferedLen - %x, pUSBDStatus - %x\n",
30            DeviceHandle,
31            FdoDevice,
32            SetupPacket,
33            Buffer,
34            Length,
35            TransferedLen,
36            pUSBDStatus);
37 
38     KeInitializeEvent(&Event, NotificationEvent, FALSE);
39 
40     Urb = ExAllocatePoolWithTag(NonPagedPool,
41                                 sizeof(struct _URB_CONTROL_TRANSFER),
42                                 USB_PORT_TAG);
43 
44     if (Urb)
45     {
46         InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
47 
48         RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_TRANSFER));
49 
50         RtlCopyMemory(Urb->UrbControlTransfer.SetupPacket,
51                       SetupPacket,
52                       sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
53 
54         Urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
55         Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
56         Urb->UrbHeader.UsbdDeviceHandle = DeviceHandle;
57         Urb->UrbHeader.UsbdFlags = 0;
58 
59         Urb->UrbControlTransfer.PipeHandle = &DeviceHandle->PipeHandle;
60         Urb->UrbControlTransfer.TransferBufferLength = Length;
61         Urb->UrbControlTransfer.TransferBuffer = Buffer;
62         Urb->UrbControlTransfer.TransferBufferMDL = NULL;
63 
64         Urb->UrbControlTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK |
65                                                 USBD_TRANSFER_DIRECTION;
66 
67         if (SetupPacket->bmRequestType.Dir != BMREQUEST_DEVICE_TO_HOST)
68         {
69             Urb->UrbControlTransfer.TransferFlags &= ~USBD_TRANSFER_DIRECTION_IN;
70         }
71 
72         Status = STATUS_SUCCESS;
73 
74         if (Length)
75         {
76             Mdl = IoAllocateMdl(Buffer, Length, FALSE, FALSE, NULL);
77 
78             Urb->UrbControlTransfer.TransferBufferMDL = Mdl;
79 
80             if (Mdl)
81             {
82                 Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_MDL;
83                 MmBuildMdlForNonPagedPool(Mdl);
84             }
85             else
86             {
87                 Status = USBPORT_USBDStatusToNtStatus(NULL,
88                                                       USBD_STATUS_INSUFFICIENT_RESOURCES);
89             }
90         }
91 
92         if (NT_SUCCESS(Status))
93         {
94             USBDStatus = USBPORT_AllocateTransfer(FdoDevice,
95                                                   Urb,
96                                                   NULL,
97                                                   NULL,
98                                                   &Event);
99 
100             if (USBD_SUCCESS(USBDStatus))
101             {
102                 InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
103 
104                 USBPORT_QueueTransferUrb(Urb);
105 
106                 KeWaitForSingleObject(&Event,
107                                       Suspended,
108                                       KernelMode,
109                                       FALSE,
110                                       NULL);
111 
112                 USBDStatus = Urb->UrbHeader.Status;
113             }
114 
115             Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
116 
117             if (TransferedLen)
118                 *TransferedLen = Urb->UrbControlTransfer.TransferBufferLength;
119 
120             if (pUSBDStatus)
121                 *pUSBDStatus = USBDStatus;
122         }
123 
124         InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
125         ExFreePoolWithTag(Urb, USB_PORT_TAG);
126     }
127     else
128     {
129         if (pUSBDStatus)
130             *pUSBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
131 
132         Status = USBPORT_USBDStatusToNtStatus(NULL,
133                                               USBD_STATUS_INSUFFICIENT_RESOURCES);
134     }
135 
136     DPRINT("USBPORT_SendSetupPacket: Status - %x\n", Status);
137     return Status;
138 }
139 
140 ULONG
141 NTAPI
142 USBPORT_GetInterfaceLength(IN PUSB_INTERFACE_DESCRIPTOR iDescriptor,
143                            IN ULONG_PTR EndDescriptors)
144 {
145     SIZE_T Length;
146     PUSB_ENDPOINT_DESCRIPTOR Descriptor;
147     ULONG ix;
148 
149     DPRINT("USBPORT_GetInterfaceLength ... \n");
150 
151     Length = iDescriptor->bLength;
152     Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)iDescriptor + Length);
153 
154     if (iDescriptor->bNumEndpoints)
155     {
156         for (ix = 0; ix < iDescriptor->bNumEndpoints; ix++)
157         {
158             while ((Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) &&
159                    (Descriptor->bLength > 0))
160             {
161                 Length += Descriptor->bLength;
162                 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
163                                                         Descriptor->bLength);
164             }
165 
166             Length += Descriptor->bLength;
167             Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
168                                                     Descriptor->bLength);
169         }
170     }
171 
172     while (((ULONG_PTR)Descriptor < EndDescriptors) &&
173            (Descriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE) &&
174            (Descriptor->bLength > 0))
175     {
176         Length += Descriptor->bLength;
177         Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
178                                                 Descriptor->bLength);
179     }
180 
181     return Length;
182 }
183 
184 PUSB_INTERFACE_DESCRIPTOR
185 NTAPI
186 USBPORT_ParseConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
187                                      IN UCHAR InterfaceNumber,
188                                      IN UCHAR Alternate,
189                                      OUT PUCHAR OutAlternate)
190 {
191     PUSB_CONFIGURATION_DESCRIPTOR TmpDescriptor;
192     PUSB_INTERFACE_DESCRIPTOR iDescriptor;
193     PUSB_INTERFACE_DESCRIPTOR OutDescriptor = NULL;
194     ULONG_PTR Descriptor = (ULONG_PTR)ConfigDescriptor;
195     ULONG_PTR EndDescriptors;
196     ULONG ix;
197 
198     DPRINT("USBPORT_ParseConfigurationDescriptor ... \n");
199 
200     if (OutAlternate)
201         *OutAlternate = 0;
202 
203     for (TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)ConfigDescriptor + ConfigDescriptor->bLength);
204          TmpDescriptor->bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE && TmpDescriptor->bDescriptorType > 0;
205          TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)TmpDescriptor + TmpDescriptor->bLength))
206     ;
207 
208     iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)TmpDescriptor;
209 
210     EndDescriptors = (ULONG_PTR)ConfigDescriptor +
211                                 ConfigDescriptor->wTotalLength;
212 
213     while ((Descriptor < EndDescriptors) &&
214            (iDescriptor->bInterfaceNumber != InterfaceNumber))
215     {
216         Descriptor = (ULONG_PTR)iDescriptor +
217                      USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
218 
219         iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
220     }
221 
222     ix = 0;
223 
224     while (Descriptor < EndDescriptors &&
225            iDescriptor->bInterfaceNumber == InterfaceNumber)
226     {
227         if (iDescriptor->bAlternateSetting == Alternate)
228             OutDescriptor = iDescriptor;
229 
230         Descriptor = (ULONG_PTR)iDescriptor +
231                      USBPORT_GetInterfaceLength(iDescriptor, EndDescriptors);
232 
233         iDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Descriptor;
234 
235         ++ix;
236     }
237 
238     if ((ix > 1) && OutAlternate)
239         *OutAlternate = 1;
240 
241     return OutDescriptor;
242 }
243 
244 USBD_STATUS
245 NTAPI
246 USBPORT_OpenInterface(IN PURB Urb,
247                       IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
248                       IN PDEVICE_OBJECT FdoDevice,
249                       IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle,
250                       IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
251                       IN OUT PUSBPORT_INTERFACE_HANDLE *iHandle,
252                       IN BOOLEAN IsSetInterface)
253 {
254     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
255     PUSBPORT_INTERFACE_HANDLE InterfaceHandle = NULL;
256     PUSBPORT_PIPE_HANDLE PipeHandle;
257     PUSB_ENDPOINT_DESCRIPTOR Descriptor;
258     PUSBD_PIPE_INFORMATION PipeInfo;
259     ULONG NumEndpoints;
260     SIZE_T Length;
261     SIZE_T HandleLength;
262     BOOLEAN IsAllocated = FALSE;
263     USHORT MaxPacketSize;
264     USHORT wMaxPacketSize;
265     ULONG ix;
266     USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
267     NTSTATUS Status;
268 
269     DPRINT("USBPORT_OpenInterface: ...\n");
270 
271     InterfaceDescriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
272                                                                InterfaceInfo->InterfaceNumber,
273                                                                InterfaceInfo->AlternateSetting,
274                                                                &InterfaceInfo->AlternateSetting);
275 
276     NumEndpoints = InterfaceDescriptor->bNumEndpoints;
277 
278     Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
279              NumEndpoints * sizeof(USBD_PIPE_INFORMATION);
280 
281     if (InterfaceInfo->AlternateSetting && IsSetInterface)
282     {
283         DPRINT1("USBPORT_OpenInterface: InterfaceInfo->AlternateSetting && IsSetInterface !\n");
284     }
285 
286     if (*iHandle)
287     {
288         InterfaceHandle = *iHandle;
289     }
290     else
291     {
292         HandleLength = FIELD_OFFSET(USBPORT_INTERFACE_HANDLE, PipeHandle) +
293                        NumEndpoints * sizeof(USBPORT_PIPE_HANDLE);
294 
295         InterfaceHandle = ExAllocatePoolWithTag(NonPagedPool,
296                                                 HandleLength,
297                                                 USB_PORT_TAG);
298 
299         if (!InterfaceHandle)
300         {
301             USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
302             goto Exit;
303         }
304 
305         RtlZeroMemory(InterfaceHandle, HandleLength);
306 
307         for (ix = 0; ix < NumEndpoints; ++ix)
308         {
309             PipeHandle = &InterfaceHandle->PipeHandle[ix];
310 
311             PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
312             PipeHandle->Endpoint = NULL;
313         }
314 
315         IsAllocated = TRUE;
316     }
317 
318     InterfaceHandle->AlternateSetting = InterfaceInfo->AlternateSetting;
319 
320     RtlCopyMemory(&InterfaceHandle->InterfaceDescriptor,
321                   InterfaceDescriptor,
322                   sizeof(USB_INTERFACE_DESCRIPTOR));
323 
324     InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
325     InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
326     InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
327     InterfaceInfo->Reserved = 0;
328     InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
329 
330     Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor +
331                                             InterfaceDescriptor->bLength);
332 
333     for (ix = 0; ix < NumEndpoints; ++ix)
334     {
335         PipeHandle = &InterfaceHandle->PipeHandle[ix];
336 
337         while (Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
338         {
339             if (Descriptor->bLength == 0)
340             {
341                 break;
342             }
343             else
344             {
345                 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
346                                                         Descriptor->bLength);
347             }
348         }
349 
350         if (InterfaceInfo->Pipes[ix].PipeFlags & USBD_PF_CHANGE_MAX_PACKET)
351         {
352             Descriptor->wMaxPacketSize = InterfaceInfo->Pipes[ix].MaximumPacketSize;
353         }
354 
355         RtlCopyMemory(&PipeHandle->EndpointDescriptor,
356                       Descriptor,
357                       sizeof(USB_ENDPOINT_DESCRIPTOR));
358 
359         PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
360         PipeHandle->PipeFlags = InterfaceInfo->Pipes[ix].PipeFlags;
361         PipeHandle->Endpoint = NULL;
362 
363         wMaxPacketSize = Descriptor->wMaxPacketSize;
364 
365         /* USB 2.0 Specification, 5.9 High-Speed, High Bandwidth Endpoints */
366         MaxPacketSize = (wMaxPacketSize & 0x7FF) * (((wMaxPacketSize >> 11) & 3) + 1);
367 
368         InterfaceInfo->Pipes[ix].EndpointAddress = Descriptor->bEndpointAddress;
369         InterfaceInfo->Pipes[ix].PipeType = Descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK;
370         InterfaceInfo->Pipes[ix].MaximumPacketSize = MaxPacketSize;
371         InterfaceInfo->Pipes[ix].PipeHandle = (USBD_PIPE_HANDLE)-1;
372         InterfaceInfo->Pipes[ix].Interval = Descriptor->bInterval;
373 
374         Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
375                                                 Descriptor->bLength);
376     }
377 
378     if (USBD_SUCCESS(USBDStatus))
379     {
380         for (ix = 0; ix < NumEndpoints; ++ix)
381         {
382             PipeInfo = &InterfaceInfo->Pipes[ix];
383             PipeHandle = &InterfaceHandle->PipeHandle[ix];
384 
385             Status = USBPORT_OpenPipe(FdoDevice,
386                                       DeviceHandle,
387                                       PipeHandle,
388                                       &USBDStatus);
389 
390             if (!NT_SUCCESS(Status))
391                 break;
392 
393             PipeInfo->PipeHandle = PipeHandle;
394         }
395 
396         if (NumEndpoints)
397         {
398             USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
399         }
400     }
401 
402 Exit:
403 
404     if (USBD_SUCCESS(USBDStatus))
405     {
406         InterfaceInfo->InterfaceHandle = InterfaceHandle;
407         *iHandle = InterfaceHandle;
408         InterfaceInfo->Length = Length;
409     }
410     else
411     {
412         if (InterfaceHandle)
413         {
414             if (NumEndpoints)
415             {
416                 DPRINT1("USBPORT_OpenInterface: USBDStatus - %lx\n", USBDStatus);
417             }
418 
419             if (IsAllocated)
420                 ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
421         }
422     }
423 
424     return USBDStatus;
425 }
426 
427 VOID
428 NTAPI
429 USBPORT_CloseConfiguration(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
430                            IN PDEVICE_OBJECT FdoDevice)
431 {
432     PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
433     PLIST_ENTRY iHandleList;
434     PUSBPORT_INTERFACE_HANDLE iHandle;
435     ULONG NumEndpoints;
436     PUSBPORT_PIPE_HANDLE PipeHandle;
437 
438     DPRINT("USBPORT_CloseConfiguration: ... \n");
439 
440     ConfigHandle = DeviceHandle->ConfigHandle;
441 
442     if (ConfigHandle)
443     {
444         iHandleList = &ConfigHandle->InterfaceHandleList;
445 
446         while (!IsListEmpty(iHandleList))
447         {
448             iHandle = CONTAINING_RECORD(iHandleList->Flink,
449                                         USBPORT_INTERFACE_HANDLE,
450                                         InterfaceLink);
451 
452             DPRINT("USBPORT_CloseConfiguration: iHandle - %p\n", iHandle);
453 
454             RemoveHeadList(iHandleList);
455 
456             NumEndpoints = iHandle->InterfaceDescriptor.bNumEndpoints;
457 
458             PipeHandle = &iHandle->PipeHandle[0];
459 
460             while (NumEndpoints > 0)
461             {
462                 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
463                 PipeHandle += 1;
464                 --NumEndpoints;
465             }
466 
467             ExFreePoolWithTag(iHandle, USB_PORT_TAG);
468         }
469 
470         ExFreePoolWithTag(ConfigHandle, USB_PORT_TAG);
471         DeviceHandle->ConfigHandle = NULL;
472     }
473 }
474 
475 NTSTATUS
476 NTAPI
477 USBPORT_InitInterfaceInfo(IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
478                           IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle)
479 {
480     PUSB_INTERFACE_DESCRIPTOR Descriptor;
481     PUSBD_PIPE_INFORMATION Pipe;
482     USHORT Length;
483     ULONG PipeFlags;
484     ULONG NumberOfPipes;
485     USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
486 
487     DPRINT("USBPORT_InitInterfaceInfo: InterfaceInfo - %p, ConfigHandle - %p\n",
488            InterfaceInfo,
489            ConfigHandle);
490 
491     Descriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
492                                                       InterfaceInfo->InterfaceNumber,
493                                                       InterfaceInfo->AlternateSetting,
494                                                       &InterfaceInfo->AlternateSetting);
495 
496     Length = sizeof(USBD_INTERFACE_INFORMATION) +
497              sizeof(USBD_PIPE_INFORMATION);
498 
499     if (Descriptor)
500     {
501         NumberOfPipes = Descriptor->bNumEndpoints;
502 
503         Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
504                  NumberOfPipes * sizeof(USBD_PIPE_INFORMATION);
505 
506         if (InterfaceInfo->Length >= Length)
507         {
508             InterfaceInfo->Class = 0;
509             InterfaceInfo->SubClass = 0;
510             InterfaceInfo->Protocol = 0;
511             InterfaceInfo->Reserved = 0;
512             InterfaceInfo->InterfaceHandle = 0;
513             InterfaceInfo->NumberOfPipes = NumberOfPipes;
514 
515             Pipe = InterfaceInfo->Pipes;
516 
517             while (NumberOfPipes > 0)
518             {
519                 Pipe->EndpointAddress = 0;
520                 Pipe->Interval = 0;
521                 Pipe->PipeType = 0;
522                 Pipe->PipeHandle = 0;
523 
524                 PipeFlags = Pipe->PipeFlags;
525 
526                 if (PipeFlags & ~USBD_PF_VALID_MASK)
527                     USBDStatus = USBD_STATUS_INVALID_PIPE_FLAGS;
528 
529                 if (!(PipeFlags & USBD_PF_CHANGE_MAX_PACKET))
530                     Pipe->MaximumPacketSize = 0;
531 
532                 Pipe += 1;
533                 --NumberOfPipes;
534             }
535         }
536         else
537         {
538             USBDStatus = USBD_STATUS_BUFFER_TOO_SMALL;
539         }
540     }
541     else
542     {
543         USBDStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
544     }
545 
546     InterfaceInfo->Length = Length;
547     return USBDStatus;
548 }
549 
550 NTSTATUS
551 NTAPI
552 USBPORT_HandleSelectConfiguration(IN PDEVICE_OBJECT FdoDevice,
553                                   IN PIRP Irp,
554                                   IN PURB Urb)
555 {
556     PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
557     PUSBPORT_DEVICE_HANDLE DeviceHandle;
558     PUSBPORT_CONFIGURATION_HANDLE ConfigHandle = NULL;
559     PUSBD_INTERFACE_INFORMATION InterfaceInfo;
560     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
561     ULONG iNumber;
562     ULONG ix;
563     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
564     NTSTATUS Status;
565     USBD_STATUS USBDStatus;
566     PUSBPORT_DEVICE_EXTENSION FdoExtension;
567 
568     DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor %p\n",
569            Urb->UrbSelectConfiguration.ConfigurationDescriptor);
570 
571     FdoExtension = FdoDevice->DeviceExtension;
572 
573     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
574                           Executive,
575                           KernelMode,
576                           FALSE,
577                           NULL);
578 
579     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
580     ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
581 
582     if (!ConfigDescriptor)
583     {
584         DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor == NULL\n");
585 
586         RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
587 
588         SetupPacket.bmRequestType.B = 0;
589         SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
590         SetupPacket.wValue.W = 0;
591         SetupPacket.wIndex.W = 0;
592         SetupPacket.wLength = 0;
593 
594         USBPORT_SendSetupPacket(DeviceHandle,
595                                 FdoDevice,
596                                 &SetupPacket,
597                                 NULL,
598                                 0,
599                                 NULL,
600                                 NULL);
601 
602         Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
603         goto Exit;
604     }
605 
606     USBPORT_DumpingConfiguration(ConfigDescriptor);
607 
608     InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
609 
610     iNumber = 0;
611 
612     do
613     {
614         ++iNumber;
615         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
616                         ((ULONG_PTR)InterfaceInfo +
617                          InterfaceInfo->Length);
618     }
619     while ((ULONG_PTR)InterfaceInfo < (ULONG_PTR)Urb + Urb->UrbHeader.Length);
620 
621     if ((iNumber <= 0) || (iNumber != ConfigDescriptor->bNumInterfaces))
622     {
623         Status = USBPORT_USBDStatusToNtStatus(Urb,
624                                               USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR);
625         goto Exit;
626     }
627 
628     ConfigHandle = ExAllocatePoolWithTag(NonPagedPool,
629                                          ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE),
630                                          USB_PORT_TAG);
631 
632     if (!ConfigHandle)
633     {
634         Status = USBPORT_USBDStatusToNtStatus(Urb,
635                                               USBD_STATUS_INSUFFICIENT_RESOURCES);
636         goto Exit;
637     }
638 
639     RtlZeroMemory(ConfigHandle,
640                   ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE));
641 
642     InitializeListHead(&ConfigHandle->InterfaceHandleList);
643 
644     ConfigHandle->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigHandle + 1);
645 
646     RtlCopyMemory(ConfigHandle->ConfigurationDescriptor,
647                   ConfigDescriptor,
648                   ConfigDescriptor->wTotalLength);
649 
650     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
651 
652     SetupPacket.bmRequestType.B = 0;
653     SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
654     SetupPacket.wValue.W = ConfigDescriptor->bConfigurationValue;
655     SetupPacket.wIndex.W = 0;
656     SetupPacket.wLength = 0;
657 
658     USBPORT_SendSetupPacket(DeviceHandle,
659                             FdoDevice,
660                             &SetupPacket,
661                             NULL,
662                             0,
663                             NULL,
664                             &USBDStatus);
665 
666     if (USBD_ERROR(USBDStatus))
667     {
668         Status = USBPORT_USBDStatusToNtStatus(Urb,
669                                               USBD_STATUS_SET_CONFIG_FAILED);
670         goto Exit;
671     }
672 
673     if (iNumber <= 0)
674     {
675         Status = USBPORT_USBDStatusToNtStatus(Urb,
676                                               USBD_STATUS_SUCCESS);
677 
678         goto Exit;
679     }
680 
681     InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
682 
683     for (ix = 0; ix < iNumber; ++ix)
684     {
685         USBDStatus = USBPORT_InitInterfaceInfo(InterfaceInfo,
686                                                ConfigHandle);
687 
688         InterfaceHandle = NULL;
689 
690         if (USBD_SUCCESS(USBDStatus))
691         {
692             USBDStatus = USBPORT_OpenInterface(Urb,
693                                                DeviceHandle,
694                                                FdoDevice,
695                                                ConfigHandle,
696                                                InterfaceInfo,
697                                                &InterfaceHandle,
698                                                TRUE);
699         }
700 
701         if (InterfaceHandle)
702         {
703             InsertTailList(&ConfigHandle->InterfaceHandleList,
704                            &InterfaceHandle->InterfaceLink);
705         }
706 
707         if (USBD_ERROR(USBDStatus))
708             break;
709 
710         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
711                          ((ULONG_PTR)InterfaceInfo +
712                           InterfaceInfo->Length);
713     }
714 
715     if (ix >= iNumber)
716     {
717         Status = USBPORT_USBDStatusToNtStatus(Urb,
718                                               USBD_STATUS_SUCCESS);
719     }
720     else
721     {
722         Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
723     }
724 
725 Exit:
726 
727     if (NT_SUCCESS(Status))
728     {
729         Urb->UrbSelectConfiguration.ConfigurationHandle = ConfigHandle;
730         DeviceHandle->ConfigHandle = ConfigHandle;
731     }
732     else
733     {
734         DPRINT1("USBPORT_HandleSelectConfiguration: Status %x\n", Status);
735     }
736 
737     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
738                        LOW_REALTIME_PRIORITY,
739                        1,
740                        FALSE);
741 
742     return Status;
743 }
744 
745 VOID
746 NTAPI
747 USBPORT_AddDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
748                         IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
749 {
750     PUSBPORT_DEVICE_EXTENSION FdoExtension;
751 
752     DPRINT("USBPORT_AddDeviceHandle: ... \n");
753 
754     FdoExtension = FdoDevice->DeviceExtension;
755 
756     InsertTailList(&FdoExtension->DeviceHandleList,
757                    &DeviceHandle->DeviceHandleLink);
758 }
759 
760 VOID
761 NTAPI
762 USBPORT_RemoveDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
763                            IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
764 {
765     PUSBPORT_DEVICE_EXTENSION FdoExtension;
766     KIRQL OldIrql;
767 
768     DPRINT("USBPORT_RemoveDeviceHandle \n");
769 
770     FdoExtension = FdoDevice->DeviceExtension;
771 
772     KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
773     RemoveEntryList(&DeviceHandle->DeviceHandleLink);
774     KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
775 }
776 
777 BOOLEAN
778 NTAPI
779 USBPORT_ValidateDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
780                              IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
781 {
782     PUSBPORT_DEVICE_EXTENSION FdoExtension;
783     KIRQL OldIrql;
784     PLIST_ENTRY HandleList;
785     PUSBPORT_DEVICE_HANDLE CurrentHandle;
786     BOOLEAN Result = FALSE;
787 
788     //DPRINT("USBPORT_ValidateDeviceHandle: DeviceHandle - %p\n", DeviceHandle \n");
789 
790     FdoExtension = FdoDevice->DeviceExtension;
791 
792     KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
793     if (DeviceHandle)
794     {
795         HandleList = FdoExtension->DeviceHandleList.Flink;
796 
797         while (HandleList != &FdoExtension->DeviceHandleList)
798         {
799             CurrentHandle = CONTAINING_RECORD(HandleList,
800                                               USBPORT_DEVICE_HANDLE,
801                                               DeviceHandleLink);
802 
803             if (CurrentHandle == DeviceHandle)
804             {
805                 Result = TRUE;
806                 break;
807             }
808 
809             HandleList = HandleList->Flink;
810         }
811     }
812     KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
813 
814     return Result;
815 }
816 
817 BOOLEAN
818 NTAPI
819 USBPORT_DeviceHasTransfers(IN PDEVICE_OBJECT FdoDevice,
820                            IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
821 {
822     PLIST_ENTRY PipeHandleList;
823     PUSBPORT_PIPE_HANDLE PipeHandle;
824 
825     DPRINT("USBPORT_DeviceHasTransfers: ... \n");
826 
827     PipeHandleList = DeviceHandle->PipeHandleList.Flink;
828 
829     while (PipeHandleList != &DeviceHandle->PipeHandleList)
830     {
831         PipeHandle = CONTAINING_RECORD(PipeHandleList,
832                                        USBPORT_PIPE_HANDLE,
833                                        PipeLink);
834 
835         PipeHandleList = PipeHandleList->Flink;
836 
837         if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE) &&
838             USBPORT_EndpointHasQueuedTransfers(FdoDevice, PipeHandle->Endpoint, NULL))
839         {
840             return TRUE;
841         }
842     }
843 
844     return FALSE;
845 }
846 
847 VOID
848 NTAPI
849 USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,
850                        IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
851 {
852     PLIST_ENTRY HandleList;
853     PUSBPORT_PIPE_HANDLE PipeHandle;
854     BOOLEAN Result;
855 
856     DPRINT("USBPORT_AbortAllTransfers: ... \n");
857 
858     HandleList = DeviceHandle->PipeHandleList.Flink;
859 
860     while (HandleList != &DeviceHandle->PipeHandleList)
861     {
862         PipeHandle = CONTAINING_RECORD(HandleList,
863                                        USBPORT_PIPE_HANDLE,
864                                        PipeLink);
865 
866         HandleList = HandleList->Flink;
867 
868         if (!(PipeHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
869         {
870             PipeHandle->Endpoint->Flags |= ENDPOINT_FLAG_ABORTING;
871 
872             USBPORT_AbortEndpoint(FdoDevice, PipeHandle->Endpoint, NULL);
873             USBPORT_FlushMapTransfers(FdoDevice);
874         }
875     }
876 
877     while (TRUE)
878     {
879         Result = USBPORT_DeviceHasTransfers(FdoDevice, DeviceHandle);
880 
881         if (!Result)
882             break;
883 
884         USBPORT_Wait(FdoDevice, 100);
885     }
886 }
887 
888 NTSTATUS
889 NTAPI
890 USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
891                      IN PDEVICE_OBJECT FdoDevice,
892                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
893                      IN USHORT PortStatus,
894                      IN USHORT Port)
895 {
896     PUSBPORT_DEVICE_HANDLE DeviceHandle;
897     PUSBPORT_PIPE_HANDLE PipeHandle;
898     BOOL IsOpenedPipe;
899     PVOID DeviceDescriptor;
900     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
901     SIZE_T TransferedLen;
902     SIZE_T DescriptorMinSize;
903     UCHAR MaxPacketSize;
904     PUSBPORT_DEVICE_EXTENSION FdoExtension;
905 
906     NTSTATUS Status;
907 
908     DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
909            PortStatus,
910            Port);
911 
912     FdoExtension = FdoDevice->DeviceExtension;
913 
914     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
915                           Executive,
916                           KernelMode,
917                           FALSE,
918                           NULL);
919 
920     if (!USBPORT_ValidateDeviceHandle(FdoDevice, HubDeviceHandle))
921     {
922         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
923                            LOW_REALTIME_PRIORITY,
924                            1,
925                            FALSE);
926 
927         DPRINT1("USBPORT_CreateDevice: Not valid hub DeviceHandle\n");
928         return STATUS_DEVICE_NOT_CONNECTED;
929     }
930 
931     if (FdoExtension->MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
932         !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
933     {
934         DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port. FIXME: Transaction Translator.\n");
935         DbgBreakPoint();
936     }
937 
938     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
939                        LOW_REALTIME_PRIORITY,
940                        1,
941                        FALSE);
942 
943     DeviceHandle = ExAllocatePoolWithTag(NonPagedPool,
944                                          sizeof(USBPORT_DEVICE_HANDLE),
945                                          USB_PORT_TAG);
946 
947     if (!DeviceHandle)
948     {
949         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceHandle\n");
950         return STATUS_INSUFFICIENT_RESOURCES;
951     }
952 
953     RtlZeroMemory(DeviceHandle, sizeof(USBPORT_DEVICE_HANDLE));
954 
955     *pUsbdDeviceHandle = NULL;
956 
957     DeviceHandle->PortNumber = Port;
958     DeviceHandle->HubDeviceHandle = HubDeviceHandle;
959 
960     if (PortStatus & USB_PORT_STATUS_LOW_SPEED)
961     {
962         DeviceHandle->DeviceSpeed = UsbLowSpeed;
963     }
964     else if (PortStatus & USB_PORT_STATUS_HIGH_SPEED)
965     {
966         DeviceHandle->DeviceSpeed = UsbHighSpeed;
967     }
968     else
969     {
970         DeviceHandle->DeviceSpeed = UsbFullSpeed;
971     }
972 
973     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
974                           Executive,
975                           KernelMode,
976                           FALSE,
977                           NULL);
978 
979     PipeHandle = &DeviceHandle->PipeHandle;
980 
981     PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
982 
983     PipeHandle->EndpointDescriptor.bLength = sizeof(PipeHandle->EndpointDescriptor);
984     PipeHandle->EndpointDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
985 
986     if (DeviceHandle->DeviceSpeed == UsbLowSpeed)
987     {
988         PipeHandle->EndpointDescriptor.wMaxPacketSize = 8;
989     }
990     else
991     {
992         PipeHandle->EndpointDescriptor.wMaxPacketSize = USB_DEFAULT_MAX_PACKET;
993     }
994 
995     InitializeListHead(&DeviceHandle->PipeHandleList);
996 
997     Status = USBPORT_OpenPipe(FdoDevice,
998                               DeviceHandle,
999                               PipeHandle,
1000                               NULL);
1001 
1002     IsOpenedPipe = NT_SUCCESS(Status);
1003 
1004     if (NT_ERROR(Status))
1005     {
1006         DPRINT1("USBPORT_CreateDevice: USBPORT_OpenPipe return - %lx\n", Status);
1007 
1008         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1009                            LOW_REALTIME_PRIORITY,
1010                            1,
1011                            FALSE);
1012 
1013         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1014 
1015         return Status;
1016     }
1017 
1018     DeviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1019                                              USB_DEFAULT_MAX_PACKET,
1020                                              USB_PORT_TAG);
1021 
1022     if (!DeviceDescriptor)
1023     {
1024         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceDescriptor\n");
1025         goto ErrorExit;
1026     }
1027 
1028     RtlZeroMemory(DeviceDescriptor, USB_DEFAULT_MAX_PACKET);
1029     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1030 
1031     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1032     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1033     SetupPacket.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1034     SetupPacket.wLength = USB_DEFAULT_MAX_PACKET;
1035 
1036     TransferedLen = 0;
1037 
1038     Status = USBPORT_SendSetupPacket(DeviceHandle,
1039                                      FdoDevice,
1040                                      &SetupPacket,
1041                                      DeviceDescriptor,
1042                                      USB_DEFAULT_MAX_PACKET,
1043                                      &TransferedLen,
1044                                      NULL);
1045 
1046     RtlCopyMemory(&DeviceHandle->DeviceDescriptor,
1047                   DeviceDescriptor,
1048                   sizeof(USB_DEVICE_DESCRIPTOR));
1049 
1050     ExFreePoolWithTag(DeviceDescriptor, USB_PORT_TAG);
1051 
1052     DescriptorMinSize = RTL_SIZEOF_THROUGH_FIELD(USB_DEVICE_DESCRIPTOR,
1053                                                  bMaxPacketSize0);
1054 
1055     if ((TransferedLen == DescriptorMinSize) && !NT_SUCCESS(Status))
1056     {
1057         Status = STATUS_SUCCESS;
1058     }
1059 
1060     if (NT_SUCCESS(Status) && (TransferedLen >= DescriptorMinSize))
1061     {
1062         if ((DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR)) &&
1063             (DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE))
1064         {
1065             MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1066 
1067             if (MaxPacketSize == 8 ||
1068                 MaxPacketSize == 16 ||
1069                 MaxPacketSize == 32 ||
1070                 MaxPacketSize == 64)
1071             {
1072                 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
1073 
1074                 *pUsbdDeviceHandle = DeviceHandle;
1075 
1076                 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1077                                    LOW_REALTIME_PRIORITY,
1078                                    1,
1079                                    FALSE);
1080 
1081                 return Status;
1082             }
1083         }
1084     }
1085 
1086     DPRINT1("USBPORT_CreateDevice: ERROR!!! TransferedLen - %x, Status - %lx\n",
1087             TransferedLen,
1088             Status);
1089 
1090 ErrorExit:
1091 
1092     // FIXME: if Transaction Translator
1093 
1094     Status = STATUS_DEVICE_DATA_ERROR;
1095 
1096     if (IsOpenedPipe)
1097     {
1098         USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1099     }
1100 
1101     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1102                        LOW_REALTIME_PRIORITY,
1103                        1,
1104                        FALSE);
1105 
1106     ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1107 
1108     return Status;
1109 }
1110 
1111 ULONG
1112 NTAPI
1113 USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)
1114 {
1115     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1116     ULONG BitMapIdx;
1117     ULONG BitNumber;
1118     ULONG ix;
1119 
1120     DPRINT("USBPORT_AllocateUsbAddress \n");
1121 
1122     FdoExtension = FdoDevice->DeviceExtension;
1123 
1124     for (ix = 0; ix < 4; ++ix)
1125     {
1126         BitMapIdx = 1;
1127 
1128         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1129         {
1130             if (!(FdoExtension->UsbAddressBitMap[ix] & BitMapIdx))
1131             {
1132                 FdoExtension->UsbAddressBitMap[ix] |= BitMapIdx;
1133                 return 32 * ix + BitNumber;
1134             }
1135 
1136             BitMapIdx <<= 2;
1137         }
1138     }
1139 
1140     return 0;
1141 }
1142 
1143 VOID
1144 NTAPI
1145 USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,
1146                        IN USHORT DeviceAddress)
1147 {
1148     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1149     ULONG ix;
1150     ULONG BitMapIdx;
1151     ULONG BitNumber;
1152     USHORT CurrentAddress;
1153 
1154     DPRINT("USBPORT_FreeUsbAddress: DeviceAddress - %x\n", DeviceAddress);
1155 
1156     FdoExtension = FdoDevice->DeviceExtension;
1157 
1158     for (ix = 0; ix < 4; ++ix)
1159     {
1160         BitMapIdx = 1;
1161         CurrentAddress = 32 * ix;
1162 
1163         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1164         {
1165             if (CurrentAddress == DeviceAddress)
1166             {
1167                 FdoExtension->UsbAddressBitMap[ix] &= ~BitMapIdx;
1168                 return;
1169             }
1170 
1171             BitMapIdx <<= 2;
1172             CurrentAddress++;
1173         }
1174     }
1175 }
1176 
1177 NTSTATUS
1178 NTAPI
1179 USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1180                          IN PDEVICE_OBJECT FdoDevice)
1181 {
1182     PUSBPORT_ENDPOINT Endpoint;
1183     USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1184     ULONG TransferedLen;
1185     USHORT DeviceAddress = 0;
1186     UCHAR MaxPacketSize;
1187     NTSTATUS Status;
1188     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1189 
1190     DPRINT("USBPORT_InitializeDevice: ... \n");
1191 
1192     ASSERT(DeviceHandle != NULL);
1193 
1194     FdoExtension = FdoDevice->DeviceExtension;
1195 
1196     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1197                           Executive,
1198                           KernelMode,
1199                           FALSE,
1200                           NULL);
1201 
1202     DeviceAddress = USBPORT_AllocateUsbAddress(FdoDevice);
1203     ASSERT(DeviceHandle->DeviceAddress == USB_DEFAULT_DEVICE_ADDRESS);
1204 
1205     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1206 
1207     CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
1208     CtrlSetup.wValue.W = DeviceAddress;
1209 
1210     Status = USBPORT_SendSetupPacket(DeviceHandle,
1211                                      FdoDevice,
1212                                      &CtrlSetup,
1213                                      NULL,
1214                                      0,
1215                                      NULL,
1216                                      NULL);
1217 
1218     DPRINT("USBPORT_InitializeDevice: DeviceAddress - %x. SendSetupPacket Status - %x\n",
1219            DeviceAddress,
1220            Status);
1221 
1222     if (!NT_SUCCESS(Status))
1223         goto ExitError;
1224 
1225     DeviceHandle->DeviceAddress = DeviceAddress;
1226     Endpoint = DeviceHandle->PipeHandle.Endpoint;
1227 
1228     Endpoint->EndpointProperties.TotalMaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1229     Endpoint->EndpointProperties.DeviceAddress = DeviceAddress;
1230 
1231     Status = USBPORT_ReopenPipe(FdoDevice, Endpoint);
1232 
1233     if (!NT_SUCCESS(Status))
1234         goto ExitError;
1235 
1236     USBPORT_Wait(FdoDevice, 10);
1237 
1238     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1239 
1240     CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1241     CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1242     CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
1243     CtrlSetup.bmRequestType.B = 0x80;
1244 
1245     Status = USBPORT_SendSetupPacket(DeviceHandle,
1246                                      FdoDevice,
1247                                      &CtrlSetup,
1248                                      &DeviceHandle->DeviceDescriptor,
1249                                      sizeof(USB_DEVICE_DESCRIPTOR),
1250                                      &TransferedLen,
1251                                      NULL);
1252 
1253     if (NT_SUCCESS(Status))
1254     {
1255         ASSERT(TransferedLen == sizeof(USB_DEVICE_DESCRIPTOR));
1256         ASSERT(DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1257         ASSERT(DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
1258 
1259         MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1260 
1261         ASSERT((MaxPacketSize == 8) ||
1262                (MaxPacketSize == 16) ||
1263                (MaxPacketSize == 32) ||
1264                (MaxPacketSize == 64));
1265     }
1266     else
1267     {
1268 ExitError:
1269         DPRINT1("USBPORT_InitializeDevice: ExitError. Status - %x\n", Status);
1270     }
1271 
1272     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1273                        LOW_REALTIME_PRIORITY,
1274                        1,
1275                        FALSE);
1276 
1277     return Status;
1278 }
1279 
1280 NTSTATUS
1281 NTAPI
1282 USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1283                          IN PDEVICE_OBJECT FdoDevice,
1284                          IN UCHAR Type,
1285                          IN PUCHAR ConfigDesc,
1286                          IN PULONG ConfigDescSize)
1287 {
1288     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1289 
1290     DPRINT("USBPORT_GetUsbDescriptor: Type - %x\n");
1291 
1292     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1293 
1294     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1295     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1296     SetupPacket.wValue.HiByte = Type;
1297     SetupPacket.wLength = (USHORT)*ConfigDescSize;
1298 
1299     return USBPORT_SendSetupPacket(DeviceHandle,
1300                                    FdoDevice,
1301                                    &SetupPacket,
1302                                    ConfigDesc,
1303                                    *ConfigDescSize,
1304                                    ConfigDescSize,
1305                                    NULL);
1306 }
1307 
1308 PUSBPORT_INTERFACE_HANDLE
1309 NTAPI
1310 USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,
1311                            IN UCHAR InterfaceNumber)
1312 {
1313     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1314     PLIST_ENTRY iHandleList;
1315     UCHAR InterfaceNum;
1316 
1317     DPRINT("USBPORT_GetInterfaceHandle: ConfigurationHandle - %p, InterfaceNumber - %p\n",
1318            ConfigurationHandle,
1319            InterfaceNumber);
1320 
1321     iHandleList = ConfigurationHandle->InterfaceHandleList.Flink;
1322 
1323     while (iHandleList &&
1324            (iHandleList != &ConfigurationHandle->InterfaceHandleList))
1325     {
1326         InterfaceHandle = CONTAINING_RECORD(iHandleList,
1327                                             USBPORT_INTERFACE_HANDLE,
1328                                             InterfaceLink);
1329 
1330         InterfaceNum = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1331 
1332         if (InterfaceNum == InterfaceNumber)
1333             return InterfaceHandle;
1334 
1335         iHandleList = InterfaceHandle->InterfaceLink.Flink;
1336     }
1337 
1338     return NULL;
1339 }
1340 
1341 NTSTATUS
1342 NTAPI
1343 USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,
1344                               IN PIRP Irp,
1345                               IN PURB Urb)
1346 {
1347     PUSBPORT_DEVICE_HANDLE DeviceHandle;
1348     PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle;
1349     PUSBD_INTERFACE_INFORMATION Interface;
1350     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1351     PUSBPORT_INTERFACE_HANDLE iHandle;
1352     PUSBPORT_PIPE_HANDLE PipeHandle;
1353     USBD_STATUS USBDStatus;
1354     USHORT Length;
1355     ULONG ix;
1356     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1357 
1358     DPRINT("USBPORT_HandleSelectInterface: ... \n");
1359 
1360     FdoExtension = FdoDevice->DeviceExtension;
1361 
1362     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1363                           Executive,
1364                           KernelMode,
1365                           FALSE,
1366                           NULL);
1367 
1368     ConfigurationHandle = Urb->UrbSelectInterface.ConfigurationHandle;
1369 
1370     Interface = &Urb->UrbSelectInterface.Interface;
1371 
1372     Length = Interface->Length + sizeof(USBD_PIPE_INFORMATION);
1373     Urb->UrbHeader.Length = Length;
1374 
1375     USBDStatus = USBPORT_InitInterfaceInfo(Interface, ConfigurationHandle);
1376 
1377     if (USBDStatus)
1378     {
1379         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1380         return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1381     }
1382 
1383     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
1384 
1385     InterfaceHandle = USBPORT_GetInterfaceHandle(ConfigurationHandle,
1386                                                  Interface->InterfaceNumber);
1387 
1388     if (InterfaceHandle)
1389     {
1390         RemoveEntryList(&InterfaceHandle->InterfaceLink);
1391 
1392         if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints)
1393         {
1394             PipeHandle = &InterfaceHandle->PipeHandle[0];
1395 
1396             for (ix = 0;
1397                  ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
1398                  ix++)
1399             {
1400                 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1401                 PipeHandle += 1;
1402             }
1403         }
1404     }
1405 
1406     iHandle = 0;
1407 
1408     USBDStatus = USBPORT_OpenInterface(Urb,
1409                                        DeviceHandle,
1410                                        FdoDevice,
1411                                        ConfigurationHandle,
1412                                        Interface,
1413                                        &iHandle,
1414                                        1);
1415 
1416     if (USBDStatus)
1417     {
1418         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1419     }
1420     else
1421     {
1422         if (InterfaceHandle)
1423             ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
1424 
1425         Interface->InterfaceHandle = iHandle;
1426 
1427         InsertTailList(&ConfigurationHandle->InterfaceHandleList,
1428                        &iHandle->InterfaceLink);
1429     }
1430 
1431     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1432                        LOW_REALTIME_PRIORITY,
1433                        1,
1434                        FALSE);
1435 
1436     return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1437 }
1438 
1439 NTSTATUS
1440 NTAPI
1441 USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
1442                      IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
1443                      IN ULONG Flags)
1444 {
1445     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1446 
1447     DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
1448            DeviceHandle,
1449            Flags);
1450 
1451     FdoExtension = FdoDevice->DeviceExtension;
1452 
1453     if ((Flags & USBD_KEEP_DEVICE_DATA) ||
1454         (Flags & USBD_MARK_DEVICE_BUSY))
1455     {
1456         return STATUS_SUCCESS;
1457     }
1458 
1459     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1460                           Executive,
1461                           KernelMode,
1462                           FALSE,
1463                           NULL);
1464 
1465     if (!USBPORT_ValidateDeviceHandle(FdoDevice, DeviceHandle))
1466     {
1467         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1468                            LOW_REALTIME_PRIORITY,
1469                            1,
1470                            FALSE);
1471 
1472         DPRINT1("USBPORT_RemoveDevice: Not valid device handle\n");
1473         return STATUS_DEVICE_NOT_CONNECTED;
1474     }
1475 
1476     USBPORT_RemoveDeviceHandle(FdoDevice, DeviceHandle);
1477 
1478     DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_REMOVED;
1479 
1480     USBPORT_AbortTransfers(FdoDevice, DeviceHandle);
1481 
1482     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock - %x\n",
1483            DeviceHandle->DeviceHandleLock);
1484 
1485     while (InterlockedDecrement(&DeviceHandle->DeviceHandleLock) >= 0)
1486     {
1487         InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
1488         USBPORT_Wait(FdoDevice, 100);
1489     }
1490 
1491     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock ok\n");
1492 
1493     if (DeviceHandle->ConfigHandle)
1494     {
1495         USBPORT_CloseConfiguration(DeviceHandle, FdoDevice);
1496     }
1497 
1498     USBPORT_ClosePipe(DeviceHandle, FdoDevice, &DeviceHandle->PipeHandle);
1499 
1500     if (DeviceHandle->DeviceAddress)
1501     {
1502         USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
1503     }
1504 
1505     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1506                        LOW_REALTIME_PRIORITY,
1507                        1,
1508                        FALSE);
1509 
1510     if (!(DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
1511     {
1512         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1513     }
1514 
1515     return STATUS_SUCCESS;
1516 }
1517 
1518 NTSTATUS
1519 NTAPI
1520 USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
1521                       IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
1522                       IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)
1523 {
1524     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1525     PLIST_ENTRY iHandleList;
1526     PUSBPORT_ENDPOINT Endpoint;
1527     USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0};
1528     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1529     NTSTATUS Status = STATUS_SUCCESS;
1530     USBD_STATUS USBDStatus;
1531     KIRQL OldIrql;
1532     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1533     PUSBPORT_PIPE_HANDLE PipeHandle;
1534     PUSBPORT_REGISTRATION_PACKET Packet;
1535 
1536     DPRINT("USBPORT_RestoreDevice: OldDeviceHandle - %p, NewDeviceHandle - %p\n",
1537            OldDeviceHandle,
1538            NewDeviceHandle);
1539 
1540     FdoExtension = FdoDevice->DeviceExtension;
1541 
1542     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1543                           Executive,
1544                           KernelMode,
1545                           FALSE,
1546                           NULL);
1547 
1548     if (!USBPORT_ValidateDeviceHandle(FdoDevice, OldDeviceHandle))
1549     {
1550         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1551                            LOW_REALTIME_PRIORITY,
1552                            1,
1553                            FALSE);
1554 
1555 #ifndef NDEBUG
1556         DPRINT("USBPORT_RestoreDevice: OldDeviceHandle not valid\n");
1557         DbgBreakPoint();
1558 #endif
1559         return STATUS_DEVICE_NOT_CONNECTED;
1560     }
1561 
1562     if (!USBPORT_ValidateDeviceHandle(FdoDevice, NewDeviceHandle))
1563     {
1564         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1565                            LOW_REALTIME_PRIORITY,
1566                            1,
1567                            FALSE);
1568 #ifndef NDEBUG
1569         DPRINT("USBPORT_RestoreDevice: NewDeviceHandle not valid\n");
1570         DbgBreakPoint();
1571 #endif
1572         return STATUS_DEVICE_NOT_CONNECTED;
1573     }
1574 
1575     USBPORT_RemoveDeviceHandle(FdoDevice, OldDeviceHandle);
1576     USBPORT_AbortTransfers(FdoDevice, OldDeviceHandle);
1577 
1578     while (InterlockedDecrement(&OldDeviceHandle->DeviceHandleLock) >= 0)
1579     {
1580         InterlockedIncrement(&OldDeviceHandle->DeviceHandleLock);
1581         USBPORT_Wait(FdoDevice, 100);
1582     }
1583 
1584     if (sizeof(USB_DEVICE_DESCRIPTOR) == RtlCompareMemory(&NewDeviceHandle->DeviceDescriptor,
1585                                                           &OldDeviceHandle->DeviceDescriptor,
1586                                                           sizeof(USB_DEVICE_DESCRIPTOR)))
1587     {
1588         NewDeviceHandle->ConfigHandle = OldDeviceHandle->ConfigHandle;
1589 
1590         if (OldDeviceHandle->ConfigHandle)
1591         {
1592             RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1593 
1594             SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1595             SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
1596             SetupPacket.wValue.W = OldDeviceHandle->ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
1597             SetupPacket.wIndex.W = 0;
1598             SetupPacket.wLength = 0;
1599 
1600             USBPORT_SendSetupPacket(NewDeviceHandle,
1601                                     FdoDevice,
1602                                     &SetupPacket,
1603                                     NULL,
1604                                     0,
1605                                     NULL,
1606                                     &USBDStatus);
1607 
1608             if (USBD_ERROR(USBDStatus))
1609                 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
1610 
1611             if (NT_SUCCESS(Status))
1612             {
1613                 iHandleList = NewDeviceHandle->ConfigHandle->InterfaceHandleList.Flink;
1614 
1615                 while (iHandleList &&
1616                        iHandleList != &NewDeviceHandle->ConfigHandle->InterfaceHandleList)
1617                 {
1618                     InterfaceHandle = CONTAINING_RECORD(iHandleList,
1619                                                         USBPORT_INTERFACE_HANDLE,
1620                                                         InterfaceLink);
1621 
1622                     if (InterfaceHandle->AlternateSetting)
1623                     {
1624                         RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1625 
1626                         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1627                         SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
1628                         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
1629 
1630                         SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
1631                         SetupPacket.wValue.W = InterfaceHandle->InterfaceDescriptor.bAlternateSetting;
1632                         SetupPacket.wIndex.W = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1633                         SetupPacket.wLength = 0;
1634 
1635                         USBPORT_SendSetupPacket(NewDeviceHandle,
1636                                                 FdoDevice,
1637                                                 &SetupPacket,
1638                                                 NULL,
1639                                                 0,
1640                                                 NULL,
1641                                                 &USBDStatus);
1642                     }
1643 
1644                     iHandleList = iHandleList->Flink;
1645                 }
1646             }
1647         }
1648 
1649         if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_INITIALIZED)
1650         {
1651             DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
1652             NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
1653         }
1654 
1655         while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
1656         {
1657             PipeHandle = CONTAINING_RECORD(OldDeviceHandle->PipeHandleList.Flink,
1658                                            USBPORT_PIPE_HANDLE,
1659                                            PipeLink);
1660 
1661             DPRINT("USBPORT_RestoreDevice: PipeHandle - %p\n", PipeHandle);
1662 
1663             USBPORT_RemovePipeHandle(OldDeviceHandle, PipeHandle);
1664 
1665             if (PipeHandle != &OldDeviceHandle->PipeHandle)
1666             {
1667                 USBPORT_AddPipeHandle(NewDeviceHandle, PipeHandle);
1668 
1669                 if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
1670                 {
1671                     Endpoint = PipeHandle->Endpoint;
1672                     Endpoint->DeviceHandle = NewDeviceHandle;
1673                     Endpoint->EndpointProperties.DeviceAddress = NewDeviceHandle->DeviceAddress;
1674 
1675                     Packet = &FdoExtension->MiniPortInterface->Packet;
1676 
1677                     if (!(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1678                     {
1679                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock,
1680                                           &OldIrql);
1681 
1682                         Packet->ReopenEndpoint(FdoExtension->MiniPortExt,
1683                                                &Endpoint->EndpointProperties,
1684                                                Endpoint + 1);
1685 
1686                         Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
1687                                                       Endpoint + 1,
1688                                                       0);
1689 
1690                         Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
1691                                                   Endpoint + 1,
1692                                                   USBPORT_ENDPOINT_RUN);
1693 
1694                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1695                                           OldIrql);
1696                     }
1697                     else
1698                     {
1699                         MiniportCloseEndpoint(FdoDevice, Endpoint);
1700 
1701                         RtlZeroMemory(Endpoint + 1, Packet->MiniPortEndpointSize);
1702 
1703                         RtlZeroMemory((PVOID)Endpoint->EndpointProperties.BufferVA,
1704                                       Endpoint->EndpointProperties.BufferLength);
1705 
1706                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1707 
1708                         Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
1709                                                           &Endpoint->EndpointProperties,
1710                                                           &EndpointRequirements);
1711 
1712                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1713                                           OldIrql);
1714 
1715                         MiniportOpenEndpoint(FdoDevice, Endpoint);
1716 
1717                         Endpoint->Flags &= ~(ENDPOINT_FLAG_NUKE |
1718                                              ENDPOINT_FLAG_ABORTING);
1719 
1720                         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
1721                                           &Endpoint->EndpointOldIrql);
1722 
1723                         if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
1724                         {
1725                             KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1726 
1727                             Packet->SetEndpointState(FdoExtension->MiniPortExt,
1728                                                      Endpoint + 1,
1729                                                      USBPORT_ENDPOINT_ACTIVE);
1730 
1731                             KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1732                         }
1733 
1734                         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1735                                           Endpoint->EndpointOldIrql);
1736                     }
1737                 }
1738             }
1739         }
1740 
1741         USBPORT_AddPipeHandle(OldDeviceHandle, &OldDeviceHandle->PipeHandle);
1742     }
1743     else
1744     {
1745 #ifndef NDEBUG
1746         DPRINT("USBPORT_RestoreDevice: New DeviceDescriptor != Old DeviceDescriptor\n");
1747         DbgBreakPoint();
1748 #endif
1749         Status = STATUS_UNSUCCESSFUL;
1750     }
1751 
1752     USBPORT_ClosePipe(OldDeviceHandle, FdoDevice, &OldDeviceHandle->PipeHandle);
1753 
1754     if (OldDeviceHandle->DeviceAddress != 0)
1755         USBPORT_FreeUsbAddress(FdoDevice, OldDeviceHandle->DeviceAddress);
1756 
1757     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1758                        LOW_REALTIME_PRIORITY,
1759                        1,
1760                        FALSE);
1761 
1762     ExFreePoolWithTag(OldDeviceHandle, USB_PORT_TAG);
1763 
1764     return Status;
1765 }
1766 
1767 NTSTATUS
1768 NTAPI
1769 USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
1770                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1771                      IN ULONG TtNumber)
1772 {
1773     DPRINT1("USBPORT_InitializeTT: UNIMPLEMENTED. FIXME. \n");
1774     return STATUS_SUCCESS;
1775 }
1776 
1777 NTSTATUS
1778 NTAPI
1779 USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
1780                         IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1781                         IN ULONG TtCount)
1782 {
1783     NTSTATUS Status;
1784     ULONG ix;
1785 
1786     DPRINT("USBPORT_Initialize20Hub \n");
1787 
1788     if (!HubDeviceHandle)
1789     {
1790         return STATUS_INVALID_PARAMETER;
1791     }
1792 
1793     if (HubDeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB)
1794     {
1795         return STATUS_SUCCESS;
1796     }
1797 
1798     if (TtCount == 0)
1799     {
1800         HubDeviceHandle->TtCount = 0;
1801         return STATUS_SUCCESS;
1802     }
1803 
1804     for (ix = 0; ix < TtCount; ++ix)
1805     {
1806         Status = USBPORT_InitializeTT(FdoDevice, HubDeviceHandle, ix + 1);
1807 
1808         if (!NT_SUCCESS(Status))
1809             break;
1810     }
1811 
1812     HubDeviceHandle->TtCount = TtCount;
1813 
1814     return Status;
1815 }