xref: /reactos/drivers/usb/usbport/device.c (revision f2df3bf0)
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     SIZE_T 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 PUSB2_TT_EXTENSION
889 NTAPI
890 USBPORT_GetTt(IN PDEVICE_OBJECT FdoDevice,
891               IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
892               OUT PUSHORT OutPort,
893               OUT PUSBPORT_DEVICE_HANDLE * OutHubDeviceHandle)
894 {
895     PUSBPORT_DEVICE_HANDLE DeviceHandle = HubDeviceHandle;
896     ULONG TtCount;
897     PLIST_ENTRY Entry;
898     PUSB2_TT_EXTENSION TtExtension = NULL;
899 
900     DPRINT("USBPORT_GetTt: HubDeviceHandle - %p\n", HubDeviceHandle);
901 
902     *OutHubDeviceHandle = NULL;
903 
904     while (DeviceHandle->DeviceSpeed != UsbHighSpeed)
905     {
906         DPRINT("USBPORT_GetTt: DeviceHandle - %p, DeviceHandle->PortNumber - %X\n",
907                DeviceHandle,
908                DeviceHandle->PortNumber);
909 
910         *OutPort = DeviceHandle->PortNumber;
911 
912         DeviceHandle = DeviceHandle->HubDeviceHandle;
913 
914         if (!DeviceHandle)
915             return NULL;
916     }
917 
918     TtCount = DeviceHandle->TtCount;
919 
920     if (!TtCount)
921         return NULL;
922 
923     if (IsListEmpty(&DeviceHandle->TtList))
924         return NULL;
925 
926     Entry = DeviceHandle->TtList.Flink;
927 
928     if (TtCount > 1)
929     {
930         while (Entry != &DeviceHandle->TtList)
931         {
932             ASSERT(Entry != NULL);
933 
934             TtExtension = CONTAINING_RECORD(Entry,
935                                             USB2_TT_EXTENSION,
936                                             Link);
937 
938             if (TtExtension->TtNumber == *OutPort)
939                 break;
940 
941             Entry = Entry->Flink;
942 
943             TtExtension = NULL;
944         }
945     }
946     else
947     {
948         TtExtension = CONTAINING_RECORD(Entry,
949                                         USB2_TT_EXTENSION,
950                                         Link);
951     }
952 
953     *OutHubDeviceHandle = DeviceHandle;
954 
955     return TtExtension;
956 }
957 
958 NTSTATUS
959 NTAPI
960 USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
961                      IN PDEVICE_OBJECT FdoDevice,
962                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
963                      IN USHORT PortStatus,
964                      IN USHORT Port)
965 {
966     PUSBPORT_DEVICE_HANDLE TtDeviceHandle = NULL;
967     PUSB2_TT_EXTENSION TtExtension = NULL;
968     USHORT port;
969     PUSBPORT_DEVICE_HANDLE DeviceHandle;
970     PUSBPORT_PIPE_HANDLE PipeHandle;
971     BOOL IsOpenedPipe;
972     PVOID DeviceDescriptor;
973     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
974     ULONG TransferedLen;
975     ULONG DescriptorMinSize;
976     UCHAR MaxPacketSize;
977     PUSBPORT_DEVICE_EXTENSION FdoExtension;
978     PUSBPORT_REGISTRATION_PACKET Packet;
979     NTSTATUS Status;
980 
981     DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
982            PortStatus,
983            Port);
984 
985     FdoExtension = FdoDevice->DeviceExtension;
986     Packet = &FdoExtension->MiniPortInterface->Packet;
987 
988     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
989                           Executive,
990                           KernelMode,
991                           FALSE,
992                           NULL);
993 
994     if (!USBPORT_ValidateDeviceHandle(FdoDevice, HubDeviceHandle))
995     {
996         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
997                            LOW_REALTIME_PRIORITY,
998                            1,
999                            FALSE);
1000 
1001         DPRINT1("USBPORT_CreateDevice: Not valid hub DeviceHandle\n");
1002         return STATUS_DEVICE_NOT_CONNECTED;
1003     }
1004 
1005     port = Port;
1006 
1007     if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
1008         !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
1009     {
1010         DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port\n");
1011 
1012         TtExtension = USBPORT_GetTt(FdoDevice,
1013                                     HubDeviceHandle,
1014                                     &port,
1015                                     &TtDeviceHandle);
1016 
1017         DPRINT("USBPORT_CreateDevice: TtDeviceHandle - %p, port - %x\n",
1018                TtDeviceHandle,
1019                port);
1020     }
1021 
1022     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1023                        LOW_REALTIME_PRIORITY,
1024                        1,
1025                        FALSE);
1026 
1027     DeviceHandle = ExAllocatePoolWithTag(NonPagedPool,
1028                                          sizeof(USBPORT_DEVICE_HANDLE),
1029                                          USB_PORT_TAG);
1030 
1031     if (!DeviceHandle)
1032     {
1033         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceHandle\n");
1034         return STATUS_INSUFFICIENT_RESOURCES;
1035     }
1036 
1037     RtlZeroMemory(DeviceHandle, sizeof(USBPORT_DEVICE_HANDLE));
1038 
1039     *pUsbdDeviceHandle = NULL;
1040 
1041     DeviceHandle->TtExtension = TtExtension;
1042     DeviceHandle->PortNumber = Port;
1043     DeviceHandle->HubDeviceHandle = HubDeviceHandle;
1044 
1045     if (PortStatus & USB_PORT_STATUS_LOW_SPEED)
1046     {
1047         DeviceHandle->DeviceSpeed = UsbLowSpeed;
1048     }
1049     else if (PortStatus & USB_PORT_STATUS_HIGH_SPEED)
1050     {
1051         DeviceHandle->DeviceSpeed = UsbHighSpeed;
1052     }
1053     else
1054     {
1055         DeviceHandle->DeviceSpeed = UsbFullSpeed;
1056     }
1057 
1058     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1059                           Executive,
1060                           KernelMode,
1061                           FALSE,
1062                           NULL);
1063 
1064     PipeHandle = &DeviceHandle->PipeHandle;
1065 
1066     PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
1067 
1068     PipeHandle->EndpointDescriptor.bLength = sizeof(PipeHandle->EndpointDescriptor);
1069     PipeHandle->EndpointDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
1070 
1071     if (DeviceHandle->DeviceSpeed == UsbLowSpeed)
1072     {
1073         PipeHandle->EndpointDescriptor.wMaxPacketSize = 8;
1074     }
1075     else
1076     {
1077         PipeHandle->EndpointDescriptor.wMaxPacketSize = USB_DEFAULT_MAX_PACKET;
1078     }
1079 
1080     InitializeListHead(&DeviceHandle->PipeHandleList);
1081     InitializeListHead(&DeviceHandle->TtList);
1082 
1083     Status = USBPORT_OpenPipe(FdoDevice,
1084                               DeviceHandle,
1085                               PipeHandle,
1086                               NULL);
1087 
1088     IsOpenedPipe = NT_SUCCESS(Status);
1089 
1090     if (NT_ERROR(Status))
1091     {
1092         DPRINT1("USBPORT_CreateDevice: USBPORT_OpenPipe return - %lx\n", Status);
1093 
1094         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1095                            LOW_REALTIME_PRIORITY,
1096                            1,
1097                            FALSE);
1098 
1099         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1100 
1101         return Status;
1102     }
1103 
1104     DeviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1105                                              USB_DEFAULT_MAX_PACKET,
1106                                              USB_PORT_TAG);
1107 
1108     if (!DeviceDescriptor)
1109     {
1110         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceDescriptor\n");
1111         goto ErrorExit;
1112     }
1113 
1114     RtlZeroMemory(DeviceDescriptor, USB_DEFAULT_MAX_PACKET);
1115     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1116 
1117     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1118     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1119     SetupPacket.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1120     SetupPacket.wLength = USB_DEFAULT_MAX_PACKET;
1121 
1122     TransferedLen = 0;
1123 
1124     Status = USBPORT_SendSetupPacket(DeviceHandle,
1125                                      FdoDevice,
1126                                      &SetupPacket,
1127                                      DeviceDescriptor,
1128                                      USB_DEFAULT_MAX_PACKET,
1129                                      &TransferedLen,
1130                                      NULL);
1131 
1132     RtlCopyMemory(&DeviceHandle->DeviceDescriptor,
1133                   DeviceDescriptor,
1134                   sizeof(USB_DEVICE_DESCRIPTOR));
1135 
1136     ExFreePoolWithTag(DeviceDescriptor, USB_PORT_TAG);
1137 
1138     DescriptorMinSize = RTL_SIZEOF_THROUGH_FIELD(USB_DEVICE_DESCRIPTOR,
1139                                                  bMaxPacketSize0);
1140 
1141     if ((TransferedLen == DescriptorMinSize) && !NT_SUCCESS(Status))
1142     {
1143         Status = STATUS_SUCCESS;
1144     }
1145 
1146     if (NT_SUCCESS(Status) && (TransferedLen >= DescriptorMinSize))
1147     {
1148         if ((DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR)) &&
1149             (DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE))
1150         {
1151             MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1152 
1153             if (MaxPacketSize == 8 ||
1154                 MaxPacketSize == 16 ||
1155                 MaxPacketSize == 32 ||
1156                 MaxPacketSize == 64)
1157             {
1158                 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
1159 
1160                 *pUsbdDeviceHandle = DeviceHandle;
1161 
1162                 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1163                                    LOW_REALTIME_PRIORITY,
1164                                    1,
1165                                    FALSE);
1166 
1167                 return Status;
1168             }
1169         }
1170     }
1171 
1172     DPRINT1("USBPORT_CreateDevice: ERROR!!! TransferedLen - %x, Status - %lx\n",
1173             TransferedLen,
1174             Status);
1175 
1176 ErrorExit:
1177 
1178     if (TtExtension && TtDeviceHandle)
1179     {
1180         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_OTHER;
1181         SetupPacket.bmRequestType.Reserved = 0;
1182         SetupPacket.bmRequestType.Type = BMREQUEST_CLASS;
1183         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1184 
1185         /* Table 11-15.  Hub Class Requests */
1186         if (TtDeviceHandle == HubDeviceHandle)
1187         {
1188             SetupPacket.bRequest = USB_REQUEST_RESET_TT;
1189         }
1190         else
1191         {
1192             SetupPacket.bRequest = USB_REQUEST_CLEAR_TT_BUFFER;
1193         }
1194 
1195         SetupPacket.wValue.LowByte = 0;
1196         SetupPacket.wValue.HiByte = 0;
1197         SetupPacket.wIndex.W = port;
1198         SetupPacket.wLength = 0;
1199 
1200         USBPORT_SendSetupPacket(TtDeviceHandle,
1201                                 FdoDevice,
1202                                 &SetupPacket,
1203                                 NULL,
1204                                 0,
1205                                 NULL,
1206                                 NULL);
1207     }
1208 
1209     Status = STATUS_DEVICE_DATA_ERROR;
1210 
1211     if (IsOpenedPipe)
1212     {
1213         USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1214     }
1215 
1216     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1217                        LOW_REALTIME_PRIORITY,
1218                        1,
1219                        FALSE);
1220 
1221     ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1222 
1223     return Status;
1224 }
1225 
1226 ULONG
1227 NTAPI
1228 USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)
1229 {
1230     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1231     ULONG BitMapIdx;
1232     ULONG BitNumber;
1233     ULONG ix;
1234 
1235     DPRINT("USBPORT_AllocateUsbAddress \n");
1236 
1237     FdoExtension = FdoDevice->DeviceExtension;
1238 
1239     for (ix = 0; ix < 4; ++ix)
1240     {
1241         BitMapIdx = 1;
1242 
1243         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1244         {
1245             if (!(FdoExtension->UsbAddressBitMap[ix] & BitMapIdx))
1246             {
1247                 FdoExtension->UsbAddressBitMap[ix] |= BitMapIdx;
1248                 return 32 * ix + BitNumber;
1249             }
1250 
1251             BitMapIdx <<= 2;
1252         }
1253     }
1254 
1255     return 0;
1256 }
1257 
1258 VOID
1259 NTAPI
1260 USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,
1261                        IN USHORT DeviceAddress)
1262 {
1263     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1264     ULONG ix;
1265     ULONG BitMapIdx;
1266     ULONG BitNumber;
1267     USHORT CurrentAddress;
1268 
1269     DPRINT("USBPORT_FreeUsbAddress: DeviceAddress - %x\n", DeviceAddress);
1270 
1271     FdoExtension = FdoDevice->DeviceExtension;
1272 
1273     for (ix = 0; ix < 4; ++ix)
1274     {
1275         BitMapIdx = 1;
1276         CurrentAddress = 32 * ix;
1277 
1278         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1279         {
1280             if (CurrentAddress == DeviceAddress)
1281             {
1282                 FdoExtension->UsbAddressBitMap[ix] &= ~BitMapIdx;
1283                 return;
1284             }
1285 
1286             BitMapIdx <<= 2;
1287             CurrentAddress++;
1288         }
1289     }
1290 }
1291 
1292 NTSTATUS
1293 NTAPI
1294 USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1295                          IN PDEVICE_OBJECT FdoDevice)
1296 {
1297     PUSBPORT_ENDPOINT Endpoint;
1298     USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1299     ULONG TransferedLen;
1300     USHORT DeviceAddress = 0;
1301     UCHAR MaxPacketSize;
1302     NTSTATUS Status;
1303     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1304 
1305     DPRINT("USBPORT_InitializeDevice: ... \n");
1306 
1307     ASSERT(DeviceHandle != NULL);
1308 
1309     FdoExtension = FdoDevice->DeviceExtension;
1310 
1311     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1312                           Executive,
1313                           KernelMode,
1314                           FALSE,
1315                           NULL);
1316 
1317     DeviceAddress = USBPORT_AllocateUsbAddress(FdoDevice);
1318     ASSERT(DeviceHandle->DeviceAddress == USB_DEFAULT_DEVICE_ADDRESS);
1319 
1320     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1321 
1322     CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
1323     CtrlSetup.wValue.W = DeviceAddress;
1324 
1325     Status = USBPORT_SendSetupPacket(DeviceHandle,
1326                                      FdoDevice,
1327                                      &CtrlSetup,
1328                                      NULL,
1329                                      0,
1330                                      NULL,
1331                                      NULL);
1332 
1333     DPRINT("USBPORT_InitializeDevice: DeviceAddress - %x. SendSetupPacket Status - %x\n",
1334            DeviceAddress,
1335            Status);
1336 
1337     if (!NT_SUCCESS(Status))
1338         goto ExitError;
1339 
1340     DeviceHandle->DeviceAddress = DeviceAddress;
1341     Endpoint = DeviceHandle->PipeHandle.Endpoint;
1342 
1343     Endpoint->EndpointProperties.TotalMaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1344     Endpoint->EndpointProperties.DeviceAddress = DeviceAddress;
1345 
1346     Status = USBPORT_ReopenPipe(FdoDevice, Endpoint);
1347 
1348     if (!NT_SUCCESS(Status))
1349         goto ExitError;
1350 
1351     USBPORT_Wait(FdoDevice, 10);
1352 
1353     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1354 
1355     CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1356     CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1357     CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
1358     CtrlSetup.bmRequestType.B = 0x80;
1359 
1360     Status = USBPORT_SendSetupPacket(DeviceHandle,
1361                                      FdoDevice,
1362                                      &CtrlSetup,
1363                                      &DeviceHandle->DeviceDescriptor,
1364                                      sizeof(USB_DEVICE_DESCRIPTOR),
1365                                      &TransferedLen,
1366                                      NULL);
1367 
1368     if (NT_SUCCESS(Status))
1369     {
1370         ASSERT(TransferedLen == sizeof(USB_DEVICE_DESCRIPTOR));
1371         ASSERT(DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1372         ASSERT(DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
1373 
1374         MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1375 
1376         ASSERT((MaxPacketSize == 8) ||
1377                (MaxPacketSize == 16) ||
1378                (MaxPacketSize == 32) ||
1379                (MaxPacketSize == 64));
1380 
1381         if (DeviceHandle->DeviceSpeed == UsbHighSpeed &&
1382             DeviceHandle->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_HUB)
1383         {
1384             DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_USB2HUB;
1385         }
1386     }
1387     else
1388     {
1389 ExitError:
1390         DPRINT1("USBPORT_InitializeDevice: ExitError. Status - %x\n", Status);
1391     }
1392 
1393     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1394                        LOW_REALTIME_PRIORITY,
1395                        1,
1396                        FALSE);
1397 
1398     return Status;
1399 }
1400 
1401 NTSTATUS
1402 NTAPI
1403 USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1404                          IN PDEVICE_OBJECT FdoDevice,
1405                          IN UCHAR Type,
1406                          IN PUCHAR ConfigDesc,
1407                          IN PULONG ConfigDescSize)
1408 {
1409     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1410 
1411     DPRINT("USBPORT_GetUsbDescriptor: Type - %x\n");
1412 
1413     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1414 
1415     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1416     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1417     SetupPacket.wValue.HiByte = Type;
1418     SetupPacket.wLength = (USHORT)*ConfigDescSize;
1419 
1420     return USBPORT_SendSetupPacket(DeviceHandle,
1421                                    FdoDevice,
1422                                    &SetupPacket,
1423                                    ConfigDesc,
1424                                    *ConfigDescSize,
1425                                    ConfigDescSize,
1426                                    NULL);
1427 }
1428 
1429 PUSBPORT_INTERFACE_HANDLE
1430 NTAPI
1431 USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,
1432                            IN UCHAR InterfaceNumber)
1433 {
1434     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1435     PLIST_ENTRY iHandleList;
1436     UCHAR InterfaceNum;
1437 
1438     DPRINT("USBPORT_GetInterfaceHandle: ConfigurationHandle - %p, InterfaceNumber - %p\n",
1439            ConfigurationHandle,
1440            InterfaceNumber);
1441 
1442     iHandleList = ConfigurationHandle->InterfaceHandleList.Flink;
1443 
1444     while (iHandleList &&
1445            (iHandleList != &ConfigurationHandle->InterfaceHandleList))
1446     {
1447         InterfaceHandle = CONTAINING_RECORD(iHandleList,
1448                                             USBPORT_INTERFACE_HANDLE,
1449                                             InterfaceLink);
1450 
1451         InterfaceNum = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1452 
1453         if (InterfaceNum == InterfaceNumber)
1454             return InterfaceHandle;
1455 
1456         iHandleList = InterfaceHandle->InterfaceLink.Flink;
1457     }
1458 
1459     return NULL;
1460 }
1461 
1462 NTSTATUS
1463 NTAPI
1464 USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,
1465                               IN PIRP Irp,
1466                               IN PURB Urb)
1467 {
1468     PUSBPORT_DEVICE_HANDLE DeviceHandle;
1469     PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle;
1470     PUSBD_INTERFACE_INFORMATION Interface;
1471     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1472     PUSBPORT_INTERFACE_HANDLE iHandle;
1473     PUSBPORT_PIPE_HANDLE PipeHandle;
1474     USBD_STATUS USBDStatus;
1475     USHORT Length;
1476     ULONG ix;
1477     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1478 
1479     DPRINT("USBPORT_HandleSelectInterface: ... \n");
1480 
1481     FdoExtension = FdoDevice->DeviceExtension;
1482 
1483     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1484                           Executive,
1485                           KernelMode,
1486                           FALSE,
1487                           NULL);
1488 
1489     ConfigurationHandle = Urb->UrbSelectInterface.ConfigurationHandle;
1490 
1491     Interface = &Urb->UrbSelectInterface.Interface;
1492 
1493     Length = Interface->Length + sizeof(USBD_PIPE_INFORMATION);
1494     Urb->UrbHeader.Length = Length;
1495 
1496     USBDStatus = USBPORT_InitInterfaceInfo(Interface, ConfigurationHandle);
1497 
1498     if (USBDStatus)
1499     {
1500         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1501         return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1502     }
1503 
1504     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
1505 
1506     InterfaceHandle = USBPORT_GetInterfaceHandle(ConfigurationHandle,
1507                                                  Interface->InterfaceNumber);
1508 
1509     if (InterfaceHandle)
1510     {
1511         RemoveEntryList(&InterfaceHandle->InterfaceLink);
1512 
1513         if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints)
1514         {
1515             PipeHandle = &InterfaceHandle->PipeHandle[0];
1516 
1517             for (ix = 0;
1518                  ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
1519                  ix++)
1520             {
1521                 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1522                 PipeHandle += 1;
1523             }
1524         }
1525     }
1526 
1527     iHandle = 0;
1528 
1529     USBDStatus = USBPORT_OpenInterface(Urb,
1530                                        DeviceHandle,
1531                                        FdoDevice,
1532                                        ConfigurationHandle,
1533                                        Interface,
1534                                        &iHandle,
1535                                        1);
1536 
1537     if (USBDStatus)
1538     {
1539         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1540     }
1541     else
1542     {
1543         if (InterfaceHandle)
1544             ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
1545 
1546         Interface->InterfaceHandle = iHandle;
1547 
1548         InsertTailList(&ConfigurationHandle->InterfaceHandleList,
1549                        &iHandle->InterfaceLink);
1550     }
1551 
1552     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1553                        LOW_REALTIME_PRIORITY,
1554                        1,
1555                        FALSE);
1556 
1557     return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1558 }
1559 
1560 NTSTATUS
1561 NTAPI
1562 USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
1563                      IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
1564                      IN ULONG Flags)
1565 {
1566     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1567     PUSB2_TT_EXTENSION TtExtension;
1568     ULONG ix;
1569     KIRQL OldIrql;
1570 
1571     DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
1572            DeviceHandle,
1573            Flags);
1574 
1575     FdoExtension = FdoDevice->DeviceExtension;
1576 
1577     if ((Flags & USBD_KEEP_DEVICE_DATA) ||
1578         (Flags & USBD_MARK_DEVICE_BUSY))
1579     {
1580         return STATUS_SUCCESS;
1581     }
1582 
1583     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1584                           Executive,
1585                           KernelMode,
1586                           FALSE,
1587                           NULL);
1588 
1589     if (!USBPORT_ValidateDeviceHandle(FdoDevice, DeviceHandle))
1590     {
1591         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1592                            LOW_REALTIME_PRIORITY,
1593                            1,
1594                            FALSE);
1595 
1596         DPRINT1("USBPORT_RemoveDevice: Not valid device handle\n");
1597         return STATUS_DEVICE_NOT_CONNECTED;
1598     }
1599 
1600     USBPORT_RemoveDeviceHandle(FdoDevice, DeviceHandle);
1601 
1602     DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_REMOVED;
1603 
1604     USBPORT_AbortTransfers(FdoDevice, DeviceHandle);
1605 
1606     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock - %x\n",
1607            DeviceHandle->DeviceHandleLock);
1608 
1609     while (InterlockedDecrement(&DeviceHandle->DeviceHandleLock) >= 0)
1610     {
1611         InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
1612         USBPORT_Wait(FdoDevice, 100);
1613     }
1614 
1615     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock ok\n");
1616 
1617     if (DeviceHandle->ConfigHandle)
1618     {
1619         USBPORT_CloseConfiguration(DeviceHandle, FdoDevice);
1620     }
1621 
1622     USBPORT_ClosePipe(DeviceHandle, FdoDevice, &DeviceHandle->PipeHandle);
1623 
1624     if (DeviceHandle->DeviceAddress)
1625     {
1626         USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
1627     }
1628 
1629     if (!IsListEmpty(&DeviceHandle->TtList))
1630     {
1631         DPRINT1("USBPORT_RemoveDevice: DeviceHandle->TtList not empty\n");
1632     }
1633 
1634     while (!IsListEmpty(&DeviceHandle->TtList))
1635     {
1636         TtExtension = CONTAINING_RECORD(DeviceHandle->TtList.Flink,
1637                                         USB2_TT_EXTENSION,
1638                                         Link);
1639 
1640         RemoveHeadList(&DeviceHandle->TtList);
1641 
1642         DPRINT("USBPORT_RemoveDevice: TtExtension - %p\n", TtExtension);
1643 
1644         KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
1645 
1646         TtExtension->Flags |= USB2_TT_EXTENSION_FLAG_DELETED;
1647 
1648         if (IsListEmpty(&TtExtension->EndpointList))
1649         {
1650             USBPORT_UpdateAllocatedBwTt(TtExtension);
1651 
1652             for (ix = 0; ix < USB2_FRAMES; ix++)
1653             {
1654                 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1655             }
1656 
1657             DPRINT("USBPORT_RemoveDevice: ExFreePoolWithTag TtExtension - %p\n", TtExtension);
1658             ExFreePoolWithTag(TtExtension, USB_PORT_TAG);
1659         }
1660 
1661         KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
1662     }
1663 
1664     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1665                        LOW_REALTIME_PRIORITY,
1666                        1,
1667                        FALSE);
1668 
1669     if (!(DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
1670     {
1671         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1672     }
1673 
1674     return STATUS_SUCCESS;
1675 }
1676 
1677 NTSTATUS
1678 NTAPI
1679 USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
1680                       IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
1681                       IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)
1682 {
1683     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1684     PLIST_ENTRY iHandleList;
1685     PUSBPORT_ENDPOINT Endpoint;
1686     USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0};
1687     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1688     NTSTATUS Status = STATUS_SUCCESS;
1689     USBD_STATUS USBDStatus;
1690     KIRQL OldIrql;
1691     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1692     PUSBPORT_PIPE_HANDLE PipeHandle;
1693     PUSBPORT_REGISTRATION_PACKET Packet;
1694 
1695     DPRINT("USBPORT_RestoreDevice: OldDeviceHandle - %p, NewDeviceHandle - %p\n",
1696            OldDeviceHandle,
1697            NewDeviceHandle);
1698 
1699     FdoExtension = FdoDevice->DeviceExtension;
1700 
1701     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1702                           Executive,
1703                           KernelMode,
1704                           FALSE,
1705                           NULL);
1706 
1707     if (!USBPORT_ValidateDeviceHandle(FdoDevice, OldDeviceHandle))
1708     {
1709         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1710                            LOW_REALTIME_PRIORITY,
1711                            1,
1712                            FALSE);
1713 
1714 #ifndef NDEBUG
1715         DPRINT("USBPORT_RestoreDevice: OldDeviceHandle not valid\n");
1716         DbgBreakPoint();
1717 #endif
1718         return STATUS_DEVICE_NOT_CONNECTED;
1719     }
1720 
1721     if (!USBPORT_ValidateDeviceHandle(FdoDevice, NewDeviceHandle))
1722     {
1723         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1724                            LOW_REALTIME_PRIORITY,
1725                            1,
1726                            FALSE);
1727 #ifndef NDEBUG
1728         DPRINT("USBPORT_RestoreDevice: NewDeviceHandle not valid\n");
1729         DbgBreakPoint();
1730 #endif
1731         return STATUS_DEVICE_NOT_CONNECTED;
1732     }
1733 
1734     USBPORT_RemoveDeviceHandle(FdoDevice, OldDeviceHandle);
1735     USBPORT_AbortTransfers(FdoDevice, OldDeviceHandle);
1736 
1737     while (InterlockedDecrement(&OldDeviceHandle->DeviceHandleLock) >= 0)
1738     {
1739         InterlockedIncrement(&OldDeviceHandle->DeviceHandleLock);
1740         USBPORT_Wait(FdoDevice, 100);
1741     }
1742 
1743     if (sizeof(USB_DEVICE_DESCRIPTOR) == RtlCompareMemory(&NewDeviceHandle->DeviceDescriptor,
1744                                                           &OldDeviceHandle->DeviceDescriptor,
1745                                                           sizeof(USB_DEVICE_DESCRIPTOR)))
1746     {
1747         NewDeviceHandle->ConfigHandle = OldDeviceHandle->ConfigHandle;
1748 
1749         if (OldDeviceHandle->ConfigHandle)
1750         {
1751             RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1752 
1753             SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1754             SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
1755             SetupPacket.wValue.W = OldDeviceHandle->ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
1756             SetupPacket.wIndex.W = 0;
1757             SetupPacket.wLength = 0;
1758 
1759             USBPORT_SendSetupPacket(NewDeviceHandle,
1760                                     FdoDevice,
1761                                     &SetupPacket,
1762                                     NULL,
1763                                     0,
1764                                     NULL,
1765                                     &USBDStatus);
1766 
1767             if (USBD_ERROR(USBDStatus))
1768                 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
1769 
1770             if (NT_SUCCESS(Status))
1771             {
1772                 iHandleList = NewDeviceHandle->ConfigHandle->InterfaceHandleList.Flink;
1773 
1774                 while (iHandleList &&
1775                        iHandleList != &NewDeviceHandle->ConfigHandle->InterfaceHandleList)
1776                 {
1777                     InterfaceHandle = CONTAINING_RECORD(iHandleList,
1778                                                         USBPORT_INTERFACE_HANDLE,
1779                                                         InterfaceLink);
1780 
1781                     if (InterfaceHandle->AlternateSetting)
1782                     {
1783                         RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1784 
1785                         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1786                         SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
1787                         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
1788 
1789                         SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
1790                         SetupPacket.wValue.W = InterfaceHandle->InterfaceDescriptor.bAlternateSetting;
1791                         SetupPacket.wIndex.W = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1792                         SetupPacket.wLength = 0;
1793 
1794                         USBPORT_SendSetupPacket(NewDeviceHandle,
1795                                                 FdoDevice,
1796                                                 &SetupPacket,
1797                                                 NULL,
1798                                                 0,
1799                                                 NULL,
1800                                                 &USBDStatus);
1801                     }
1802 
1803                     iHandleList = iHandleList->Flink;
1804                 }
1805             }
1806         }
1807 
1808         if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_USB2HUB)
1809         {
1810             DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
1811             NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
1812 
1813 #ifndef NDEBUG
1814             DbgBreakPoint();
1815 #endif
1816         }
1817 
1818         while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
1819         {
1820             PipeHandle = CONTAINING_RECORD(OldDeviceHandle->PipeHandleList.Flink,
1821                                            USBPORT_PIPE_HANDLE,
1822                                            PipeLink);
1823 
1824             DPRINT("USBPORT_RestoreDevice: PipeHandle - %p\n", PipeHandle);
1825 
1826             USBPORT_RemovePipeHandle(OldDeviceHandle, PipeHandle);
1827 
1828             if (PipeHandle != &OldDeviceHandle->PipeHandle)
1829             {
1830                 USBPORT_AddPipeHandle(NewDeviceHandle, PipeHandle);
1831 
1832                 if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
1833                 {
1834                     Endpoint = PipeHandle->Endpoint;
1835                     Endpoint->DeviceHandle = NewDeviceHandle;
1836                     Endpoint->EndpointProperties.DeviceAddress = NewDeviceHandle->DeviceAddress;
1837 
1838                     Packet = &FdoExtension->MiniPortInterface->Packet;
1839 
1840                     if (!(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1841                     {
1842                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock,
1843                                           &OldIrql);
1844 
1845                         Packet->ReopenEndpoint(FdoExtension->MiniPortExt,
1846                                                &Endpoint->EndpointProperties,
1847                                                Endpoint + 1);
1848 
1849                         Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
1850                                                       Endpoint + 1,
1851                                                       0);
1852 
1853                         Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
1854                                                   Endpoint + 1,
1855                                                   USBPORT_ENDPOINT_RUN);
1856 
1857                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1858                                           OldIrql);
1859                     }
1860                     else
1861                     {
1862                         MiniportCloseEndpoint(FdoDevice, Endpoint);
1863 
1864                         RtlZeroMemory(Endpoint + 1, Packet->MiniPortEndpointSize);
1865 
1866                         RtlZeroMemory((PVOID)Endpoint->EndpointProperties.BufferVA,
1867                                       Endpoint->EndpointProperties.BufferLength);
1868 
1869                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1870 
1871                         Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
1872                                                           &Endpoint->EndpointProperties,
1873                                                           &EndpointRequirements);
1874 
1875                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1876                                           OldIrql);
1877 
1878                         MiniportOpenEndpoint(FdoDevice, Endpoint);
1879 
1880                         Endpoint->Flags &= ~(ENDPOINT_FLAG_NUKE |
1881                                              ENDPOINT_FLAG_ABORTING);
1882 
1883                         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
1884                                           &Endpoint->EndpointOldIrql);
1885 
1886                         if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
1887                         {
1888                             KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1889 
1890                             Packet->SetEndpointState(FdoExtension->MiniPortExt,
1891                                                      Endpoint + 1,
1892                                                      USBPORT_ENDPOINT_ACTIVE);
1893 
1894                             KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1895                         }
1896 
1897                         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1898                                           Endpoint->EndpointOldIrql);
1899                     }
1900                 }
1901             }
1902         }
1903 
1904         USBPORT_AddPipeHandle(OldDeviceHandle, &OldDeviceHandle->PipeHandle);
1905     }
1906     else
1907     {
1908 #ifndef NDEBUG
1909         DPRINT("USBPORT_RestoreDevice: New DeviceDescriptor != Old DeviceDescriptor\n");
1910         DbgBreakPoint();
1911 #endif
1912         Status = STATUS_UNSUCCESSFUL;
1913     }
1914 
1915     USBPORT_ClosePipe(OldDeviceHandle, FdoDevice, &OldDeviceHandle->PipeHandle);
1916 
1917     if (OldDeviceHandle->DeviceAddress != 0)
1918         USBPORT_FreeUsbAddress(FdoDevice, OldDeviceHandle->DeviceAddress);
1919 
1920     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1921                        LOW_REALTIME_PRIORITY,
1922                        1,
1923                        FALSE);
1924 
1925     ExFreePoolWithTag(OldDeviceHandle, USB_PORT_TAG);
1926 
1927     return Status;
1928 }
1929 
1930 NTSTATUS
1931 NTAPI
1932 USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
1933                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1934                      IN ULONG TtNumber)
1935 {
1936     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1937     PUSB2_TT_EXTENSION TtExtension;
1938     ULONG ix;
1939 
1940     DPRINT("USBPORT_InitializeTT: HubDeviceHandle - %p, TtNumber - %X\n",
1941            HubDeviceHandle,
1942            TtNumber);
1943 
1944     FdoExtension = FdoDevice->DeviceExtension;
1945 
1946     TtExtension = ExAllocatePoolWithTag(NonPagedPool,
1947                                         sizeof(USB2_TT_EXTENSION),
1948                                         USB_PORT_TAG);
1949 
1950     if (!TtExtension)
1951     {
1952         DPRINT1("USBPORT_InitializeTT: ExAllocatePoolWithTag return NULL\n");
1953         return STATUS_INSUFFICIENT_RESOURCES;
1954     }
1955 
1956     DPRINT("USBPORT_InitializeTT: TtExtension - %p\n", TtExtension);
1957 
1958     RtlZeroMemory(TtExtension, sizeof(USB2_TT_EXTENSION));
1959 
1960     TtExtension->DeviceAddress = HubDeviceHandle->DeviceAddress;
1961     TtExtension->TtNumber = TtNumber;
1962     TtExtension->RootHubPdo = FdoExtension->RootHubPdo;
1963     TtExtension->BusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
1964 
1965     InitializeListHead(&TtExtension->EndpointList);
1966 
1967     /* 90% maximum allowed for periodic endpoints */
1968     for (ix = 0; ix < USB2_FRAMES; ix++)
1969     {
1970         TtExtension->Bandwidth[ix] = TtExtension->BusBandwidth -
1971                                      TtExtension->BusBandwidth / 10;
1972     }
1973 
1974     USBPORT_UpdateAllocatedBwTt(TtExtension);
1975 
1976     for (ix = 0; ix < USB2_FRAMES; ix++)
1977     {
1978         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
1979     }
1980 
1981     USB2_InitTT(FdoExtension->Usb2Extension, &TtExtension->Tt);
1982 
1983     InsertTailList(&HubDeviceHandle->TtList, &TtExtension->Link);
1984 
1985     return STATUS_SUCCESS;
1986 }
1987 
1988 NTSTATUS
1989 NTAPI
1990 USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
1991                         IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1992                         IN ULONG TtCount)
1993 {
1994     NTSTATUS Status;
1995     ULONG ix;
1996 
1997     DPRINT("USBPORT_Initialize20Hub: TtCount - %X\n", TtCount);
1998 
1999     if (!HubDeviceHandle)
2000     {
2001         return STATUS_INVALID_PARAMETER;
2002     }
2003 
2004     if (HubDeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB)
2005     {
2006         return STATUS_SUCCESS;
2007     }
2008 
2009     if (TtCount == 0)
2010     {
2011         HubDeviceHandle->TtCount = 0;
2012         return STATUS_SUCCESS;
2013     }
2014 
2015     for (ix = 0; ix < TtCount; ++ix)
2016     {
2017         Status = USBPORT_InitializeTT(FdoDevice, HubDeviceHandle, ix + 1);
2018 
2019         if (!NT_SUCCESS(Status))
2020             break;
2021     }
2022 
2023     HubDeviceHandle->TtCount = TtCount;
2024 
2025     return Status;
2026 }