xref: /reactos/drivers/usb/usbport/device.c (revision 0c2cdcae)
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
USBPORT_SendSetupPacket(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,IN PDEVICE_OBJECT FdoDevice,IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,IN PVOID Buffer,IN ULONG Length,IN OUT PULONG TransferedLen,IN OUT PUSBD_STATUS pUSBDStatus)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
USBPORT_GetInterfaceLength(IN PUSB_INTERFACE_DESCRIPTOR iDescriptor,IN ULONG_PTR EndDescriptors)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
USBPORT_ParseConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,IN UCHAR InterfaceNumber,IN UCHAR Alternate,OUT PBOOLEAN HasAlternates)186 USBPORT_ParseConfigurationDescriptor(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor,
187                                      IN UCHAR InterfaceNumber,
188                                      IN UCHAR Alternate,
189                                      OUT PBOOLEAN HasAlternates)
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 (HasAlternates)
201         *HasAlternates = FALSE;
202 
203     for (TmpDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)((ULONG_PTR)ConfigDescriptor + ConfigDescriptor->bLength);
204          TmpDescriptor->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE && TmpDescriptor->bLength > 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) && HasAlternates)
239         *HasAlternates = TRUE;
240 
241     return OutDescriptor;
242 }
243 
244 USBD_STATUS
245 NTAPI
USBPORT_OpenInterface(IN PURB Urb,IN PUSBPORT_DEVICE_HANDLE DeviceHandle,IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle,IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,IN OUT PUSBPORT_INTERFACE_HANDLE * iHandle,IN BOOLEAN SendSetInterface)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 SendSetInterface)
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     BOOLEAN HasAlternates;
260     ULONG NumEndpoints;
261     SIZE_T Length;
262     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
263     SIZE_T HandleLength;
264     BOOLEAN IsAllocated = FALSE;
265     USHORT MaxPacketSize;
266     USHORT wMaxPacketSize;
267     ULONG ix;
268     USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
269     NTSTATUS Status;
270 
271     DPRINT("USBPORT_OpenInterface: ...\n");
272 
273     InterfaceDescriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
274                                                                InterfaceInfo->InterfaceNumber,
275                                                                InterfaceInfo->AlternateSetting,
276                                                                &HasAlternates);
277 
278     NumEndpoints = InterfaceDescriptor->bNumEndpoints;
279 
280     Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
281              NumEndpoints * sizeof(USBD_PIPE_INFORMATION);
282 
283     if (HasAlternates && SendSetInterface)
284     {
285         RtlZeroMemory(&SetupPacket, sizeof(SetupPacket));
286 
287         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
288         SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
289         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
290         SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
291         SetupPacket.wValue.W = InterfaceInfo->AlternateSetting;
292         SetupPacket.wIndex.W = InterfaceInfo->InterfaceNumber;
293         SetupPacket.wLength = 0;
294 
295         USBPORT_SendSetupPacket(DeviceHandle,
296                                 FdoDevice,
297                                 &SetupPacket,
298                                 NULL,
299                                 0,
300                                 NULL,
301                                 &USBDStatus);
302         if (!USBD_SUCCESS(USBDStatus))
303         {
304             goto Exit;
305         }
306     }
307 
308     if (*iHandle)
309     {
310         InterfaceHandle = *iHandle;
311     }
312     else
313     {
314         HandleLength = FIELD_OFFSET(USBPORT_INTERFACE_HANDLE, PipeHandle) +
315                        NumEndpoints * sizeof(USBPORT_PIPE_HANDLE);
316 
317         InterfaceHandle = ExAllocatePoolWithTag(NonPagedPool,
318                                                 HandleLength,
319                                                 USB_PORT_TAG);
320 
321         if (!InterfaceHandle)
322         {
323             USBDStatus = USBD_STATUS_INSUFFICIENT_RESOURCES;
324             goto Exit;
325         }
326 
327         RtlZeroMemory(InterfaceHandle, HandleLength);
328 
329         for (ix = 0; ix < NumEndpoints; ++ix)
330         {
331             PipeHandle = &InterfaceHandle->PipeHandle[ix];
332 
333             PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
334             PipeHandle->Endpoint = NULL;
335         }
336 
337         IsAllocated = TRUE;
338     }
339 
340     InterfaceHandle->AlternateSetting = InterfaceInfo->AlternateSetting;
341 
342     RtlCopyMemory(&InterfaceHandle->InterfaceDescriptor,
343                   InterfaceDescriptor,
344                   sizeof(USB_INTERFACE_DESCRIPTOR));
345 
346     InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass;
347     InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass;
348     InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol;
349     InterfaceInfo->Reserved = 0;
350     InterfaceInfo->NumberOfPipes = InterfaceDescriptor->bNumEndpoints;
351 
352     Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor +
353                                             InterfaceDescriptor->bLength);
354 
355     for (ix = 0; ix < NumEndpoints; ++ix)
356     {
357         PipeHandle = &InterfaceHandle->PipeHandle[ix];
358 
359         while (Descriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE)
360         {
361             if (Descriptor->bLength == 0)
362             {
363                 break;
364             }
365             else
366             {
367                 Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
368                                                         Descriptor->bLength);
369             }
370         }
371 
372         if (InterfaceInfo->Pipes[ix].PipeFlags & USBD_PF_CHANGE_MAX_PACKET)
373         {
374             Descriptor->wMaxPacketSize = InterfaceInfo->Pipes[ix].MaximumPacketSize;
375         }
376 
377         RtlCopyMemory(&PipeHandle->EndpointDescriptor,
378                       Descriptor,
379                       sizeof(USB_ENDPOINT_DESCRIPTOR));
380 
381         PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
382         PipeHandle->PipeFlags = InterfaceInfo->Pipes[ix].PipeFlags;
383         PipeHandle->Endpoint = NULL;
384 
385         wMaxPacketSize = Descriptor->wMaxPacketSize;
386 
387         /* USB 2.0 Specification, 5.9 High-Speed, High Bandwidth Endpoints */
388         MaxPacketSize = (wMaxPacketSize & 0x7FF) * (((wMaxPacketSize >> 11) & 3) + 1);
389 
390         InterfaceInfo->Pipes[ix].EndpointAddress = Descriptor->bEndpointAddress;
391         InterfaceInfo->Pipes[ix].PipeType = Descriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK;
392         InterfaceInfo->Pipes[ix].MaximumPacketSize = MaxPacketSize;
393         InterfaceInfo->Pipes[ix].PipeHandle = (USBD_PIPE_HANDLE)-1;
394         InterfaceInfo->Pipes[ix].Interval = Descriptor->bInterval;
395 
396         Descriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)Descriptor +
397                                                 Descriptor->bLength);
398     }
399 
400     if (USBD_SUCCESS(USBDStatus))
401     {
402         for (ix = 0; ix < NumEndpoints; ++ix)
403         {
404             PipeInfo = &InterfaceInfo->Pipes[ix];
405             PipeHandle = &InterfaceHandle->PipeHandle[ix];
406 
407             Status = USBPORT_OpenPipe(FdoDevice,
408                                       DeviceHandle,
409                                       PipeHandle,
410                                       &USBDStatus);
411 
412             if (!NT_SUCCESS(Status))
413                 break;
414 
415             PipeInfo->PipeHandle = PipeHandle;
416         }
417 
418         if (NumEndpoints)
419         {
420             USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
421         }
422     }
423 
424 Exit:
425 
426     if (USBD_SUCCESS(USBDStatus))
427     {
428         InterfaceInfo->InterfaceHandle = InterfaceHandle;
429         *iHandle = InterfaceHandle;
430         InterfaceInfo->Length = Length;
431     }
432     else
433     {
434         if (InterfaceHandle)
435         {
436             if (NumEndpoints)
437             {
438                 DPRINT1("USBPORT_OpenInterface: USBDStatus - %lx\n", USBDStatus);
439             }
440 
441             if (IsAllocated)
442                 ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
443         }
444     }
445 
446     return USBDStatus;
447 }
448 
449 VOID
450 NTAPI
USBPORT_CloseConfiguration(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,IN PDEVICE_OBJECT FdoDevice)451 USBPORT_CloseConfiguration(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
452                            IN PDEVICE_OBJECT FdoDevice)
453 {
454     PUSBPORT_CONFIGURATION_HANDLE ConfigHandle;
455     PLIST_ENTRY iHandleList;
456     PUSBPORT_INTERFACE_HANDLE iHandle;
457     ULONG NumEndpoints;
458     PUSBPORT_PIPE_HANDLE PipeHandle;
459 
460     DPRINT("USBPORT_CloseConfiguration: ... \n");
461 
462     ConfigHandle = DeviceHandle->ConfigHandle;
463 
464     if (ConfigHandle)
465     {
466         iHandleList = &ConfigHandle->InterfaceHandleList;
467 
468         while (!IsListEmpty(iHandleList))
469         {
470             iHandle = CONTAINING_RECORD(iHandleList->Flink,
471                                         USBPORT_INTERFACE_HANDLE,
472                                         InterfaceLink);
473 
474             DPRINT("USBPORT_CloseConfiguration: iHandle - %p\n", iHandle);
475 
476             RemoveHeadList(iHandleList);
477 
478             NumEndpoints = iHandle->InterfaceDescriptor.bNumEndpoints;
479 
480             PipeHandle = &iHandle->PipeHandle[0];
481 
482             while (NumEndpoints > 0)
483             {
484                 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
485                 PipeHandle += 1;
486                 --NumEndpoints;
487             }
488 
489             ExFreePoolWithTag(iHandle, USB_PORT_TAG);
490         }
491 
492         ExFreePoolWithTag(ConfigHandle, USB_PORT_TAG);
493         DeviceHandle->ConfigHandle = NULL;
494     }
495 }
496 
497 NTSTATUS
498 NTAPI
USBPORT_InitInterfaceInfo(IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle)499 USBPORT_InitInterfaceInfo(IN PUSBD_INTERFACE_INFORMATION InterfaceInfo,
500                           IN PUSBPORT_CONFIGURATION_HANDLE ConfigHandle)
501 {
502     PUSB_INTERFACE_DESCRIPTOR Descriptor;
503     PUSBD_PIPE_INFORMATION Pipe;
504     SIZE_T Length;
505     ULONG PipeFlags;
506     ULONG NumberOfPipes;
507     USBD_STATUS USBDStatus = USBD_STATUS_SUCCESS;
508 
509     DPRINT("USBPORT_InitInterfaceInfo: InterfaceInfo - %p, ConfigHandle - %p\n",
510            InterfaceInfo,
511            ConfigHandle);
512 
513     Descriptor = USBPORT_ParseConfigurationDescriptor(ConfigHandle->ConfigurationDescriptor,
514                                                       InterfaceInfo->InterfaceNumber,
515                                                       InterfaceInfo->AlternateSetting,
516                                                       NULL);
517 
518     Length = sizeof(USBD_INTERFACE_INFORMATION) +
519              sizeof(USBD_PIPE_INFORMATION);
520 
521     if (Descriptor)
522     {
523         NumberOfPipes = Descriptor->bNumEndpoints;
524 
525         Length = FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes) +
526                  NumberOfPipes * sizeof(USBD_PIPE_INFORMATION);
527 
528         if (InterfaceInfo->Length >= Length)
529         {
530             InterfaceInfo->Class = 0;
531             InterfaceInfo->SubClass = 0;
532             InterfaceInfo->Protocol = 0;
533             InterfaceInfo->Reserved = 0;
534             InterfaceInfo->InterfaceHandle = 0;
535             InterfaceInfo->NumberOfPipes = NumberOfPipes;
536 
537             Pipe = InterfaceInfo->Pipes;
538 
539             while (NumberOfPipes > 0)
540             {
541                 Pipe->EndpointAddress = 0;
542                 Pipe->Interval = 0;
543                 Pipe->PipeType = 0;
544                 Pipe->PipeHandle = 0;
545 
546                 PipeFlags = Pipe->PipeFlags;
547 
548                 if (PipeFlags & ~USBD_PF_VALID_MASK)
549                     USBDStatus = USBD_STATUS_INVALID_PIPE_FLAGS;
550 
551                 if (!(PipeFlags & USBD_PF_CHANGE_MAX_PACKET))
552                     Pipe->MaximumPacketSize = 0;
553 
554                 Pipe += 1;
555                 --NumberOfPipes;
556             }
557         }
558         else
559         {
560             USBDStatus = USBD_STATUS_BUFFER_TOO_SMALL;
561         }
562     }
563     else
564     {
565         USBDStatus = USBD_STATUS_INTERFACE_NOT_FOUND;
566     }
567 
568     InterfaceInfo->Length = Length;
569     return USBDStatus;
570 }
571 
572 NTSTATUS
573 NTAPI
USBPORT_HandleSelectConfiguration(IN PDEVICE_OBJECT FdoDevice,IN PIRP Irp,IN PURB Urb)574 USBPORT_HandleSelectConfiguration(IN PDEVICE_OBJECT FdoDevice,
575                                   IN PIRP Irp,
576                                   IN PURB Urb)
577 {
578     PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor;
579     PUSBPORT_DEVICE_HANDLE DeviceHandle;
580     PUSBPORT_CONFIGURATION_HANDLE ConfigHandle = NULL;
581     PUSBD_INTERFACE_INFORMATION InterfaceInfo;
582     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
583     ULONG iNumber;
584     ULONG ix;
585     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
586     NTSTATUS Status;
587     USBD_STATUS USBDStatus;
588     PUSBPORT_DEVICE_EXTENSION FdoExtension;
589 
590     DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor %p\n",
591            Urb->UrbSelectConfiguration.ConfigurationDescriptor);
592 
593     FdoExtension = FdoDevice->DeviceExtension;
594 
595     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
596                           Executive,
597                           KernelMode,
598                           FALSE,
599                           NULL);
600 
601     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
602     ConfigDescriptor = Urb->UrbSelectConfiguration.ConfigurationDescriptor;
603 
604     if (!ConfigDescriptor)
605     {
606         DPRINT("USBPORT_HandleSelectConfiguration: ConfigDescriptor == NULL\n");
607 
608         RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
609 
610         SetupPacket.bmRequestType.B = 0;
611         SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
612         SetupPacket.wValue.W = 0;
613         SetupPacket.wIndex.W = 0;
614         SetupPacket.wLength = 0;
615 
616         USBPORT_SendSetupPacket(DeviceHandle,
617                                 FdoDevice,
618                                 &SetupPacket,
619                                 NULL,
620                                 0,
621                                 NULL,
622                                 NULL);
623 
624         Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
625         goto Exit;
626     }
627 
628     USBPORT_DumpingConfiguration(ConfigDescriptor);
629 
630     InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
631 
632     iNumber = 0;
633 
634     do
635     {
636         ++iNumber;
637         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
638                         ((ULONG_PTR)InterfaceInfo +
639                          InterfaceInfo->Length);
640     }
641     while ((ULONG_PTR)InterfaceInfo < (ULONG_PTR)Urb + Urb->UrbHeader.Length);
642 
643     if ((iNumber <= 0) || (iNumber != ConfigDescriptor->bNumInterfaces))
644     {
645         Status = USBPORT_USBDStatusToNtStatus(Urb,
646                                               USBD_STATUS_INVALID_CONFIGURATION_DESCRIPTOR);
647         goto Exit;
648     }
649 
650     ConfigHandle = ExAllocatePoolWithTag(NonPagedPool,
651                                          ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE),
652                                          USB_PORT_TAG);
653 
654     if (!ConfigHandle)
655     {
656         Status = USBPORT_USBDStatusToNtStatus(Urb,
657                                               USBD_STATUS_INSUFFICIENT_RESOURCES);
658         goto Exit;
659     }
660 
661     RtlZeroMemory(ConfigHandle,
662                   ConfigDescriptor->wTotalLength + sizeof(USBPORT_CONFIGURATION_HANDLE));
663 
664     InitializeListHead(&ConfigHandle->InterfaceHandleList);
665 
666     ConfigHandle->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigHandle + 1);
667 
668     RtlCopyMemory(ConfigHandle->ConfigurationDescriptor,
669                   ConfigDescriptor,
670                   ConfigDescriptor->wTotalLength);
671 
672     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
673 
674     SetupPacket.bmRequestType.B = 0;
675     SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
676     SetupPacket.wValue.W = ConfigDescriptor->bConfigurationValue;
677     SetupPacket.wIndex.W = 0;
678     SetupPacket.wLength = 0;
679 
680     USBPORT_SendSetupPacket(DeviceHandle,
681                             FdoDevice,
682                             &SetupPacket,
683                             NULL,
684                             0,
685                             NULL,
686                             &USBDStatus);
687 
688     if (USBD_ERROR(USBDStatus))
689     {
690         Status = USBPORT_USBDStatusToNtStatus(Urb,
691                                               USBD_STATUS_SET_CONFIG_FAILED);
692         goto Exit;
693     }
694 
695     if (iNumber <= 0)
696     {
697         Status = USBPORT_USBDStatusToNtStatus(Urb,
698                                               USBD_STATUS_SUCCESS);
699 
700         goto Exit;
701     }
702 
703     InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
704 
705     for (ix = 0; ix < iNumber; ++ix)
706     {
707         USBDStatus = USBPORT_InitInterfaceInfo(InterfaceInfo,
708                                                ConfigHandle);
709 
710         InterfaceHandle = NULL;
711 
712         if (USBD_SUCCESS(USBDStatus))
713         {
714             USBDStatus = USBPORT_OpenInterface(Urb,
715                                                DeviceHandle,
716                                                FdoDevice,
717                                                ConfigHandle,
718                                                InterfaceInfo,
719                                                &InterfaceHandle,
720                                                TRUE);
721         }
722 
723         if (InterfaceHandle)
724         {
725             InsertTailList(&ConfigHandle->InterfaceHandleList,
726                            &InterfaceHandle->InterfaceLink);
727         }
728 
729         if (USBD_ERROR(USBDStatus))
730             break;
731 
732         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)
733                          ((ULONG_PTR)InterfaceInfo +
734                           InterfaceInfo->Length);
735     }
736 
737     if (ix >= iNumber)
738     {
739         Status = USBPORT_USBDStatusToNtStatus(Urb,
740                                               USBD_STATUS_SUCCESS);
741     }
742     else
743     {
744         Status = USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
745     }
746 
747 Exit:
748 
749     if (NT_SUCCESS(Status))
750     {
751         Urb->UrbSelectConfiguration.ConfigurationHandle = ConfigHandle;
752         DeviceHandle->ConfigHandle = ConfigHandle;
753     }
754     else
755     {
756         DPRINT1("USBPORT_HandleSelectConfiguration: Status %x\n", Status);
757     }
758 
759     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
760                        LOW_REALTIME_PRIORITY,
761                        1,
762                        FALSE);
763 
764     return Status;
765 }
766 
767 VOID
768 NTAPI
USBPORT_AddDeviceHandle(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE DeviceHandle)769 USBPORT_AddDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
770                         IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
771 {
772     PUSBPORT_DEVICE_EXTENSION FdoExtension;
773 
774     DPRINT("USBPORT_AddDeviceHandle: ... \n");
775 
776     FdoExtension = FdoDevice->DeviceExtension;
777 
778     InsertTailList(&FdoExtension->DeviceHandleList,
779                    &DeviceHandle->DeviceHandleLink);
780 }
781 
782 VOID
783 NTAPI
USBPORT_RemoveDeviceHandle(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE DeviceHandle)784 USBPORT_RemoveDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
785                            IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
786 {
787     PUSBPORT_DEVICE_EXTENSION FdoExtension;
788     KIRQL OldIrql;
789 
790     DPRINT("USBPORT_RemoveDeviceHandle \n");
791 
792     FdoExtension = FdoDevice->DeviceExtension;
793 
794     KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
795     RemoveEntryList(&DeviceHandle->DeviceHandleLink);
796     KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
797 }
798 
799 BOOLEAN
800 NTAPI
USBPORT_ValidateDeviceHandle(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE DeviceHandle)801 USBPORT_ValidateDeviceHandle(IN PDEVICE_OBJECT FdoDevice,
802                              IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
803 {
804     PUSBPORT_DEVICE_EXTENSION FdoExtension;
805     KIRQL OldIrql;
806     PLIST_ENTRY HandleList;
807     PUSBPORT_DEVICE_HANDLE CurrentHandle;
808     BOOLEAN Result = FALSE;
809 
810     //DPRINT("USBPORT_ValidateDeviceHandle: DeviceHandle - %p\n", DeviceHandle \n");
811 
812     FdoExtension = FdoDevice->DeviceExtension;
813 
814     KeAcquireSpinLock(&FdoExtension->DeviceHandleSpinLock, &OldIrql);
815     if (DeviceHandle)
816     {
817         HandleList = FdoExtension->DeviceHandleList.Flink;
818 
819         while (HandleList != &FdoExtension->DeviceHandleList)
820         {
821             CurrentHandle = CONTAINING_RECORD(HandleList,
822                                               USBPORT_DEVICE_HANDLE,
823                                               DeviceHandleLink);
824 
825             if (CurrentHandle == DeviceHandle)
826             {
827                 Result = TRUE;
828                 break;
829             }
830 
831             HandleList = HandleList->Flink;
832         }
833     }
834     KeReleaseSpinLock(&FdoExtension->DeviceHandleSpinLock, OldIrql);
835 
836     return Result;
837 }
838 
839 BOOLEAN
840 NTAPI
USBPORT_DeviceHasTransfers(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE DeviceHandle)841 USBPORT_DeviceHasTransfers(IN PDEVICE_OBJECT FdoDevice,
842                            IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
843 {
844     PLIST_ENTRY PipeHandleList;
845     PUSBPORT_PIPE_HANDLE PipeHandle;
846 
847     DPRINT("USBPORT_DeviceHasTransfers: ... \n");
848 
849     PipeHandleList = DeviceHandle->PipeHandleList.Flink;
850 
851     while (PipeHandleList != &DeviceHandle->PipeHandleList)
852     {
853         PipeHandle = CONTAINING_RECORD(PipeHandleList,
854                                        USBPORT_PIPE_HANDLE,
855                                        PipeLink);
856 
857         PipeHandleList = PipeHandleList->Flink;
858 
859         if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE) &&
860             USBPORT_EndpointHasQueuedTransfers(FdoDevice, PipeHandle->Endpoint, NULL))
861         {
862             return TRUE;
863         }
864     }
865 
866     return FALSE;
867 }
868 
869 VOID
870 NTAPI
USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE DeviceHandle)871 USBPORT_AbortTransfers(IN PDEVICE_OBJECT FdoDevice,
872                        IN PUSBPORT_DEVICE_HANDLE DeviceHandle)
873 {
874     PLIST_ENTRY HandleList;
875     PUSBPORT_PIPE_HANDLE PipeHandle;
876     BOOLEAN Result;
877 
878     DPRINT("USBPORT_AbortAllTransfers: ... \n");
879 
880     HandleList = DeviceHandle->PipeHandleList.Flink;
881 
882     while (HandleList != &DeviceHandle->PipeHandleList)
883     {
884         PipeHandle = CONTAINING_RECORD(HandleList,
885                                        USBPORT_PIPE_HANDLE,
886                                        PipeLink);
887 
888         HandleList = HandleList->Flink;
889 
890         if (!(PipeHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
891         {
892             PipeHandle->Endpoint->Flags |= ENDPOINT_FLAG_ABORTING;
893 
894             USBPORT_AbortEndpoint(FdoDevice, PipeHandle->Endpoint, NULL);
895             USBPORT_FlushMapTransfers(FdoDevice);
896         }
897     }
898 
899     while (TRUE)
900     {
901         Result = USBPORT_DeviceHasTransfers(FdoDevice, DeviceHandle);
902 
903         if (!Result)
904             break;
905 
906         USBPORT_Wait(FdoDevice, 100);
907     }
908 }
909 
910 PUSB2_TT_EXTENSION
911 NTAPI
USBPORT_GetTt(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,OUT PUSHORT OutPort,OUT PUSBPORT_DEVICE_HANDLE * OutHubDeviceHandle)912 USBPORT_GetTt(IN PDEVICE_OBJECT FdoDevice,
913               IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
914               OUT PUSHORT OutPort,
915               OUT PUSBPORT_DEVICE_HANDLE * OutHubDeviceHandle)
916 {
917     PUSBPORT_DEVICE_HANDLE DeviceHandle = HubDeviceHandle;
918     ULONG TtCount;
919     PLIST_ENTRY Entry;
920     PUSB2_TT_EXTENSION TtExtension = NULL;
921 
922     DPRINT("USBPORT_GetTt: HubDeviceHandle - %p\n", HubDeviceHandle);
923 
924     *OutHubDeviceHandle = NULL;
925 
926     while (DeviceHandle->DeviceSpeed != UsbHighSpeed)
927     {
928         DPRINT("USBPORT_GetTt: DeviceHandle - %p, DeviceHandle->PortNumber - %X\n",
929                DeviceHandle,
930                DeviceHandle->PortNumber);
931 
932         *OutPort = DeviceHandle->PortNumber;
933 
934         DeviceHandle = DeviceHandle->HubDeviceHandle;
935 
936         if (!DeviceHandle)
937             return NULL;
938     }
939 
940     TtCount = DeviceHandle->TtCount;
941 
942     if (!TtCount)
943         return NULL;
944 
945     if (IsListEmpty(&DeviceHandle->TtList))
946         return NULL;
947 
948     Entry = DeviceHandle->TtList.Flink;
949 
950     if (TtCount > 1)
951     {
952         while (Entry != &DeviceHandle->TtList)
953         {
954             ASSERT(Entry != NULL);
955 
956             TtExtension = CONTAINING_RECORD(Entry,
957                                             USB2_TT_EXTENSION,
958                                             Link);
959 
960             if (TtExtension->TtNumber == *OutPort)
961                 break;
962 
963             Entry = Entry->Flink;
964 
965             TtExtension = NULL;
966         }
967     }
968     else
969     {
970         TtExtension = CONTAINING_RECORD(Entry,
971                                         USB2_TT_EXTENSION,
972                                         Link);
973     }
974 
975     *OutHubDeviceHandle = DeviceHandle;
976 
977     return TtExtension;
978 }
979 
980 NTSTATUS
981 NTAPI
USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE * pUsbdDeviceHandle,IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,IN USHORT PortStatus,IN USHORT Port)982 USBPORT_CreateDevice(IN OUT PUSB_DEVICE_HANDLE *pUsbdDeviceHandle,
983                      IN PDEVICE_OBJECT FdoDevice,
984                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
985                      IN USHORT PortStatus,
986                      IN USHORT Port)
987 {
988     PUSBPORT_DEVICE_HANDLE TtDeviceHandle = NULL;
989     PUSB2_TT_EXTENSION TtExtension = NULL;
990     USHORT port;
991     PUSBPORT_DEVICE_HANDLE DeviceHandle;
992     PUSBPORT_PIPE_HANDLE PipeHandle;
993     BOOL IsOpenedPipe;
994     PVOID DeviceDescriptor;
995     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
996     ULONG TransferedLen;
997     ULONG DescriptorMinSize;
998     UCHAR MaxPacketSize;
999     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1000     PUSBPORT_REGISTRATION_PACKET Packet;
1001     NTSTATUS Status;
1002 
1003     DPRINT("USBPORT_CreateDevice: PortStatus - %p, Port - %x\n",
1004            PortStatus,
1005            Port);
1006 
1007     FdoExtension = FdoDevice->DeviceExtension;
1008     Packet = &FdoExtension->MiniPortInterface->Packet;
1009 
1010     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1011                           Executive,
1012                           KernelMode,
1013                           FALSE,
1014                           NULL);
1015 
1016     if (!USBPORT_ValidateDeviceHandle(FdoDevice, HubDeviceHandle))
1017     {
1018         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1019                            LOW_REALTIME_PRIORITY,
1020                            1,
1021                            FALSE);
1022 
1023         DPRINT1("USBPORT_CreateDevice: Not valid hub DeviceHandle\n");
1024         return STATUS_DEVICE_NOT_CONNECTED;
1025     }
1026 
1027     port = Port;
1028 
1029     if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2 &&
1030         !(PortStatus & USB_PORT_STATUS_HIGH_SPEED))
1031     {
1032         DPRINT1("USBPORT_CreateDevice: USB1 device connected to USB2 port\n");
1033 
1034         TtExtension = USBPORT_GetTt(FdoDevice,
1035                                     HubDeviceHandle,
1036                                     &port,
1037                                     &TtDeviceHandle);
1038 
1039         DPRINT("USBPORT_CreateDevice: TtDeviceHandle - %p, port - %x\n",
1040                TtDeviceHandle,
1041                port);
1042     }
1043 
1044     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1045                        LOW_REALTIME_PRIORITY,
1046                        1,
1047                        FALSE);
1048 
1049     DeviceHandle = ExAllocatePoolWithTag(NonPagedPool,
1050                                          sizeof(USBPORT_DEVICE_HANDLE),
1051                                          USB_PORT_TAG);
1052 
1053     if (!DeviceHandle)
1054     {
1055         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceHandle\n");
1056         return STATUS_INSUFFICIENT_RESOURCES;
1057     }
1058 
1059     RtlZeroMemory(DeviceHandle, sizeof(USBPORT_DEVICE_HANDLE));
1060 
1061     *pUsbdDeviceHandle = NULL;
1062 
1063     DeviceHandle->TtExtension = TtExtension;
1064     DeviceHandle->PortNumber = Port;
1065     DeviceHandle->HubDeviceHandle = HubDeviceHandle;
1066 
1067     if (PortStatus & USB_PORT_STATUS_LOW_SPEED)
1068     {
1069         DeviceHandle->DeviceSpeed = UsbLowSpeed;
1070     }
1071     else if (PortStatus & USB_PORT_STATUS_HIGH_SPEED)
1072     {
1073         DeviceHandle->DeviceSpeed = UsbHighSpeed;
1074     }
1075     else
1076     {
1077         DeviceHandle->DeviceSpeed = UsbFullSpeed;
1078     }
1079 
1080     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1081                           Executive,
1082                           KernelMode,
1083                           FALSE,
1084                           NULL);
1085 
1086     PipeHandle = &DeviceHandle->PipeHandle;
1087 
1088     PipeHandle->Flags = PIPE_HANDLE_FLAG_CLOSED;
1089 
1090     PipeHandle->EndpointDescriptor.bLength = sizeof(PipeHandle->EndpointDescriptor);
1091     PipeHandle->EndpointDescriptor.bDescriptorType = USB_ENDPOINT_DESCRIPTOR_TYPE;
1092 
1093     if (DeviceHandle->DeviceSpeed == UsbLowSpeed)
1094     {
1095         PipeHandle->EndpointDescriptor.wMaxPacketSize = 8;
1096     }
1097     else
1098     {
1099         PipeHandle->EndpointDescriptor.wMaxPacketSize = USB_DEFAULT_MAX_PACKET;
1100     }
1101 
1102     InitializeListHead(&DeviceHandle->PipeHandleList);
1103     InitializeListHead(&DeviceHandle->TtList);
1104 
1105     Status = USBPORT_OpenPipe(FdoDevice,
1106                               DeviceHandle,
1107                               PipeHandle,
1108                               NULL);
1109 
1110     IsOpenedPipe = NT_SUCCESS(Status);
1111 
1112     if (NT_ERROR(Status))
1113     {
1114         DPRINT1("USBPORT_CreateDevice: USBPORT_OpenPipe return - %lx\n", Status);
1115 
1116         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1117                            LOW_REALTIME_PRIORITY,
1118                            1,
1119                            FALSE);
1120 
1121         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1122 
1123         return Status;
1124     }
1125 
1126     DeviceDescriptor = ExAllocatePoolWithTag(NonPagedPool,
1127                                              USB_DEFAULT_MAX_PACKET,
1128                                              USB_PORT_TAG);
1129 
1130     if (!DeviceDescriptor)
1131     {
1132         DPRINT1("USBPORT_CreateDevice: Not allocated DeviceDescriptor\n");
1133         goto ErrorExit;
1134     }
1135 
1136     RtlZeroMemory(DeviceDescriptor, USB_DEFAULT_MAX_PACKET);
1137     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1138 
1139     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1140     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1141     SetupPacket.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1142     SetupPacket.wLength = USB_DEFAULT_MAX_PACKET;
1143 
1144     TransferedLen = 0;
1145 
1146     Status = USBPORT_SendSetupPacket(DeviceHandle,
1147                                      FdoDevice,
1148                                      &SetupPacket,
1149                                      DeviceDescriptor,
1150                                      USB_DEFAULT_MAX_PACKET,
1151                                      &TransferedLen,
1152                                      NULL);
1153 
1154     RtlCopyMemory(&DeviceHandle->DeviceDescriptor,
1155                   DeviceDescriptor,
1156                   sizeof(USB_DEVICE_DESCRIPTOR));
1157 
1158     ExFreePoolWithTag(DeviceDescriptor, USB_PORT_TAG);
1159 
1160     DescriptorMinSize = RTL_SIZEOF_THROUGH_FIELD(USB_DEVICE_DESCRIPTOR,
1161                                                  bMaxPacketSize0);
1162 
1163     if ((TransferedLen == DescriptorMinSize) && !NT_SUCCESS(Status))
1164     {
1165         Status = STATUS_SUCCESS;
1166     }
1167 
1168     if (NT_SUCCESS(Status) && (TransferedLen >= DescriptorMinSize))
1169     {
1170         if ((DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR)) &&
1171             (DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE))
1172         {
1173             MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1174 
1175             if (MaxPacketSize == 8 ||
1176                 MaxPacketSize == 16 ||
1177                 MaxPacketSize == 32 ||
1178                 MaxPacketSize == 64)
1179             {
1180                 USBPORT_AddDeviceHandle(FdoDevice, DeviceHandle);
1181 
1182                 *pUsbdDeviceHandle = DeviceHandle;
1183 
1184                 KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1185                                    LOW_REALTIME_PRIORITY,
1186                                    1,
1187                                    FALSE);
1188 
1189                 return Status;
1190             }
1191         }
1192     }
1193 
1194     DPRINT1("USBPORT_CreateDevice: ERROR!!! TransferedLen - %x, Status - %lx\n",
1195             TransferedLen,
1196             Status);
1197 
1198 ErrorExit:
1199 
1200     if (TtExtension && TtDeviceHandle)
1201     {
1202         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_OTHER;
1203         SetupPacket.bmRequestType.Reserved = 0;
1204         SetupPacket.bmRequestType.Type = BMREQUEST_CLASS;
1205         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1206 
1207         /* Table 11-15.  Hub Class Requests */
1208         if (TtDeviceHandle == HubDeviceHandle)
1209         {
1210             SetupPacket.bRequest = USB_REQUEST_RESET_TT;
1211         }
1212         else
1213         {
1214             SetupPacket.bRequest = USB_REQUEST_CLEAR_TT_BUFFER;
1215         }
1216 
1217         SetupPacket.wValue.LowByte = 0;
1218         SetupPacket.wValue.HiByte = 0;
1219         SetupPacket.wIndex.W = port;
1220         SetupPacket.wLength = 0;
1221 
1222         USBPORT_SendSetupPacket(TtDeviceHandle,
1223                                 FdoDevice,
1224                                 &SetupPacket,
1225                                 NULL,
1226                                 0,
1227                                 NULL,
1228                                 NULL);
1229     }
1230 
1231     Status = STATUS_DEVICE_DATA_ERROR;
1232 
1233     if (IsOpenedPipe)
1234     {
1235         USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1236     }
1237 
1238     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1239                        LOW_REALTIME_PRIORITY,
1240                        1,
1241                        FALSE);
1242 
1243     ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1244 
1245     return Status;
1246 }
1247 
1248 ULONG
1249 NTAPI
USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)1250 USBPORT_AllocateUsbAddress(IN PDEVICE_OBJECT FdoDevice)
1251 {
1252     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1253     ULONG BitMapIdx;
1254     ULONG BitNumber;
1255     ULONG ix;
1256 
1257     DPRINT("USBPORT_AllocateUsbAddress \n");
1258 
1259     FdoExtension = FdoDevice->DeviceExtension;
1260 
1261     for (ix = 0; ix < 4; ++ix)
1262     {
1263         BitMapIdx = 1;
1264 
1265         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1266         {
1267             if (!(FdoExtension->UsbAddressBitMap[ix] & BitMapIdx))
1268             {
1269                 FdoExtension->UsbAddressBitMap[ix] |= BitMapIdx;
1270                 return 32 * ix + BitNumber;
1271             }
1272 
1273             BitMapIdx <<= 2;
1274         }
1275     }
1276 
1277     return 0;
1278 }
1279 
1280 VOID
1281 NTAPI
USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,IN USHORT DeviceAddress)1282 USBPORT_FreeUsbAddress(IN PDEVICE_OBJECT FdoDevice,
1283                        IN USHORT DeviceAddress)
1284 {
1285     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1286     ULONG ix;
1287     ULONG BitMapIdx;
1288     ULONG BitNumber;
1289     USHORT CurrentAddress;
1290 
1291     DPRINT("USBPORT_FreeUsbAddress: DeviceAddress - %x\n", DeviceAddress);
1292 
1293     FdoExtension = FdoDevice->DeviceExtension;
1294 
1295     for (ix = 0; ix < 4; ++ix)
1296     {
1297         BitMapIdx = 1;
1298         CurrentAddress = 32 * ix;
1299 
1300         for (BitNumber = 0; BitNumber < 32; ++BitNumber)
1301         {
1302             if (CurrentAddress == DeviceAddress)
1303             {
1304                 FdoExtension->UsbAddressBitMap[ix] &= ~BitMapIdx;
1305                 return;
1306             }
1307 
1308             BitMapIdx <<= 2;
1309             CurrentAddress++;
1310         }
1311     }
1312 }
1313 
1314 NTSTATUS
1315 NTAPI
USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,IN PDEVICE_OBJECT FdoDevice)1316 USBPORT_InitializeDevice(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1317                          IN PDEVICE_OBJECT FdoDevice)
1318 {
1319     PUSBPORT_ENDPOINT Endpoint;
1320     USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
1321     ULONG TransferedLen;
1322     USHORT DeviceAddress = 0;
1323     UCHAR MaxPacketSize;
1324     NTSTATUS Status;
1325     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1326 
1327     DPRINT("USBPORT_InitializeDevice: ... \n");
1328 
1329     ASSERT(DeviceHandle != NULL);
1330 
1331     FdoExtension = FdoDevice->DeviceExtension;
1332 
1333     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1334                           Executive,
1335                           KernelMode,
1336                           FALSE,
1337                           NULL);
1338 
1339     DeviceAddress = USBPORT_AllocateUsbAddress(FdoDevice);
1340     ASSERT(DeviceHandle->DeviceAddress == USB_DEFAULT_DEVICE_ADDRESS);
1341 
1342     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1343 
1344     CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
1345     CtrlSetup.wValue.W = DeviceAddress;
1346 
1347     Status = USBPORT_SendSetupPacket(DeviceHandle,
1348                                      FdoDevice,
1349                                      &CtrlSetup,
1350                                      NULL,
1351                                      0,
1352                                      NULL,
1353                                      NULL);
1354 
1355     DPRINT("USBPORT_InitializeDevice: DeviceAddress - %x. SendSetupPacket Status - %x\n",
1356            DeviceAddress,
1357            Status);
1358 
1359     if (!NT_SUCCESS(Status))
1360         goto ExitError;
1361 
1362     DeviceHandle->DeviceAddress = DeviceAddress;
1363     Endpoint = DeviceHandle->PipeHandle.Endpoint;
1364 
1365     Endpoint->EndpointProperties.TotalMaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1366     Endpoint->EndpointProperties.DeviceAddress = DeviceAddress;
1367 
1368     Status = USBPORT_ReopenPipe(FdoDevice, Endpoint);
1369 
1370     if (!NT_SUCCESS(Status))
1371         goto ExitError;
1372 
1373     USBPORT_Wait(FdoDevice, 10);
1374 
1375     RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1376 
1377     CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1378     CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
1379     CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
1380     CtrlSetup.bmRequestType.B = 0x80;
1381 
1382     Status = USBPORT_SendSetupPacket(DeviceHandle,
1383                                      FdoDevice,
1384                                      &CtrlSetup,
1385                                      &DeviceHandle->DeviceDescriptor,
1386                                      sizeof(USB_DEVICE_DESCRIPTOR),
1387                                      &TransferedLen,
1388                                      NULL);
1389 
1390     if (NT_SUCCESS(Status))
1391     {
1392         ASSERT(TransferedLen == sizeof(USB_DEVICE_DESCRIPTOR));
1393         ASSERT(DeviceHandle->DeviceDescriptor.bLength >= sizeof(USB_DEVICE_DESCRIPTOR));
1394         ASSERT(DeviceHandle->DeviceDescriptor.bDescriptorType == USB_DEVICE_DESCRIPTOR_TYPE);
1395 
1396         MaxPacketSize = DeviceHandle->DeviceDescriptor.bMaxPacketSize0;
1397 
1398         ASSERT((MaxPacketSize == 8) ||
1399                (MaxPacketSize == 16) ||
1400                (MaxPacketSize == 32) ||
1401                (MaxPacketSize == 64));
1402 
1403         if (DeviceHandle->DeviceSpeed == UsbHighSpeed &&
1404             DeviceHandle->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_HUB)
1405         {
1406             DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_USB2HUB;
1407         }
1408     }
1409     else
1410     {
1411 ExitError:
1412         DPRINT1("USBPORT_InitializeDevice: ExitError. Status - %x\n", Status);
1413     }
1414 
1415     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1416                        LOW_REALTIME_PRIORITY,
1417                        1,
1418                        FALSE);
1419 
1420     return Status;
1421 }
1422 
1423 NTSTATUS
1424 NTAPI
USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,IN PDEVICE_OBJECT FdoDevice,IN UCHAR Type,IN PUCHAR ConfigDesc,IN PULONG ConfigDescSize)1425 USBPORT_GetUsbDescriptor(IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
1426                          IN PDEVICE_OBJECT FdoDevice,
1427                          IN UCHAR Type,
1428                          IN PUCHAR ConfigDesc,
1429                          IN PULONG ConfigDescSize)
1430 {
1431     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1432 
1433     DPRINT("USBPORT_GetUsbDescriptor: Type - %x\n");
1434 
1435     RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1436 
1437     SetupPacket.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST;
1438     SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
1439     SetupPacket.wValue.HiByte = Type;
1440     SetupPacket.wLength = (USHORT)*ConfigDescSize;
1441 
1442     return USBPORT_SendSetupPacket(DeviceHandle,
1443                                    FdoDevice,
1444                                    &SetupPacket,
1445                                    ConfigDesc,
1446                                    *ConfigDescSize,
1447                                    ConfigDescSize,
1448                                    NULL);
1449 }
1450 
1451 PUSBPORT_INTERFACE_HANDLE
1452 NTAPI
USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,IN UCHAR InterfaceNumber)1453 USBPORT_GetInterfaceHandle(IN PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle,
1454                            IN UCHAR InterfaceNumber)
1455 {
1456     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1457     PLIST_ENTRY iHandleList;
1458     UCHAR InterfaceNum;
1459 
1460     DPRINT("USBPORT_GetInterfaceHandle: ConfigurationHandle - %p, InterfaceNumber - %p\n",
1461            ConfigurationHandle,
1462            InterfaceNumber);
1463 
1464     iHandleList = ConfigurationHandle->InterfaceHandleList.Flink;
1465 
1466     while (iHandleList &&
1467            (iHandleList != &ConfigurationHandle->InterfaceHandleList))
1468     {
1469         InterfaceHandle = CONTAINING_RECORD(iHandleList,
1470                                             USBPORT_INTERFACE_HANDLE,
1471                                             InterfaceLink);
1472 
1473         InterfaceNum = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1474 
1475         if (InterfaceNum == InterfaceNumber)
1476             return InterfaceHandle;
1477 
1478         iHandleList = InterfaceHandle->InterfaceLink.Flink;
1479     }
1480 
1481     return NULL;
1482 }
1483 
1484 NTSTATUS
1485 NTAPI
USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,IN PIRP Irp,IN PURB Urb)1486 USBPORT_HandleSelectInterface(IN PDEVICE_OBJECT FdoDevice,
1487                               IN PIRP Irp,
1488                               IN PURB Urb)
1489 {
1490     PUSBPORT_DEVICE_HANDLE DeviceHandle;
1491     PUSBPORT_CONFIGURATION_HANDLE ConfigurationHandle;
1492     PUSBD_INTERFACE_INFORMATION Interface;
1493     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1494     PUSBPORT_INTERFACE_HANDLE iHandle;
1495     PUSBPORT_PIPE_HANDLE PipeHandle;
1496     USBD_STATUS USBDStatus;
1497     USHORT Length;
1498     ULONG ix;
1499     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1500 
1501     DPRINT("USBPORT_HandleSelectInterface: ... \n");
1502 
1503     FdoExtension = FdoDevice->DeviceExtension;
1504 
1505     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1506                           Executive,
1507                           KernelMode,
1508                           FALSE,
1509                           NULL);
1510 
1511     ConfigurationHandle = Urb->UrbSelectInterface.ConfigurationHandle;
1512 
1513     Interface = &Urb->UrbSelectInterface.Interface;
1514 
1515     Length = Interface->Length + sizeof(USBD_PIPE_INFORMATION);
1516     Urb->UrbHeader.Length = Length;
1517 
1518     USBDStatus = USBPORT_InitInterfaceInfo(Interface, ConfigurationHandle);
1519 
1520     if (USBDStatus)
1521     {
1522         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1523         return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1524     }
1525 
1526     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
1527 
1528     InterfaceHandle = USBPORT_GetInterfaceHandle(ConfigurationHandle,
1529                                                  Interface->InterfaceNumber);
1530 
1531     if (InterfaceHandle)
1532     {
1533         RemoveEntryList(&InterfaceHandle->InterfaceLink);
1534 
1535         if (InterfaceHandle->InterfaceDescriptor.bNumEndpoints)
1536         {
1537             PipeHandle = &InterfaceHandle->PipeHandle[0];
1538 
1539             for (ix = 0;
1540                  ix < InterfaceHandle->InterfaceDescriptor.bNumEndpoints;
1541                  ix++)
1542             {
1543                 USBPORT_ClosePipe(DeviceHandle, FdoDevice, PipeHandle);
1544                 PipeHandle += 1;
1545             }
1546         }
1547     }
1548 
1549     iHandle = 0;
1550 
1551     USBDStatus = USBPORT_OpenInterface(Urb,
1552                                        DeviceHandle,
1553                                        FdoDevice,
1554                                        ConfigurationHandle,
1555                                        Interface,
1556                                        &iHandle,
1557                                        TRUE);
1558 
1559     if (USBDStatus)
1560     {
1561         Interface->InterfaceHandle = (USBD_INTERFACE_HANDLE)-1;
1562     }
1563     else
1564     {
1565         if (InterfaceHandle)
1566             ExFreePoolWithTag(InterfaceHandle, USB_PORT_TAG);
1567 
1568         Interface->InterfaceHandle = iHandle;
1569 
1570         InsertTailList(&ConfigurationHandle->InterfaceHandleList,
1571                        &iHandle->InterfaceLink);
1572     }
1573 
1574     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1575                        LOW_REALTIME_PRIORITY,
1576                        1,
1577                        FALSE);
1578 
1579     return USBPORT_USBDStatusToNtStatus(Urb, USBDStatus);
1580 }
1581 
1582 NTSTATUS
1583 NTAPI
USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,IN ULONG Flags)1584 USBPORT_RemoveDevice(IN PDEVICE_OBJECT FdoDevice,
1585                      IN OUT PUSBPORT_DEVICE_HANDLE DeviceHandle,
1586                      IN ULONG Flags)
1587 {
1588     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1589     PUSB2_TT_EXTENSION TtExtension;
1590     ULONG ix;
1591     KIRQL OldIrql;
1592 
1593     DPRINT("USBPORT_RemoveDevice: DeviceHandle - %p, Flags - %x\n",
1594            DeviceHandle,
1595            Flags);
1596 
1597     FdoExtension = FdoDevice->DeviceExtension;
1598 
1599     if ((Flags & USBD_KEEP_DEVICE_DATA) ||
1600         (Flags & USBD_MARK_DEVICE_BUSY))
1601     {
1602         return STATUS_SUCCESS;
1603     }
1604 
1605     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1606                           Executive,
1607                           KernelMode,
1608                           FALSE,
1609                           NULL);
1610 
1611     if (!USBPORT_ValidateDeviceHandle(FdoDevice, DeviceHandle))
1612     {
1613         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1614                            LOW_REALTIME_PRIORITY,
1615                            1,
1616                            FALSE);
1617 
1618         DPRINT1("USBPORT_RemoveDevice: Not valid device handle\n");
1619         return STATUS_DEVICE_NOT_CONNECTED;
1620     }
1621 
1622     USBPORT_RemoveDeviceHandle(FdoDevice, DeviceHandle);
1623 
1624     DeviceHandle->Flags |= DEVICE_HANDLE_FLAG_REMOVED;
1625 
1626     USBPORT_AbortTransfers(FdoDevice, DeviceHandle);
1627 
1628     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock - %x\n",
1629            DeviceHandle->DeviceHandleLock);
1630 
1631     while (InterlockedDecrement(&DeviceHandle->DeviceHandleLock) >= 0)
1632     {
1633         InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
1634         USBPORT_Wait(FdoDevice, 100);
1635     }
1636 
1637     DPRINT("USBPORT_RemoveDevice: DeviceHandleLock ok\n");
1638 
1639     if (DeviceHandle->ConfigHandle)
1640     {
1641         USBPORT_CloseConfiguration(DeviceHandle, FdoDevice);
1642     }
1643 
1644     USBPORT_ClosePipe(DeviceHandle, FdoDevice, &DeviceHandle->PipeHandle);
1645 
1646     if (DeviceHandle->DeviceAddress)
1647     {
1648         USBPORT_FreeUsbAddress(FdoDevice, DeviceHandle->DeviceAddress);
1649     }
1650 
1651     if (!IsListEmpty(&DeviceHandle->TtList))
1652     {
1653         DPRINT1("USBPORT_RemoveDevice: DeviceHandle->TtList not empty\n");
1654     }
1655 
1656     while (!IsListEmpty(&DeviceHandle->TtList))
1657     {
1658         TtExtension = CONTAINING_RECORD(DeviceHandle->TtList.Flink,
1659                                         USB2_TT_EXTENSION,
1660                                         Link);
1661 
1662         RemoveHeadList(&DeviceHandle->TtList);
1663 
1664         DPRINT("USBPORT_RemoveDevice: TtExtension - %p\n", TtExtension);
1665 
1666         KeAcquireSpinLock(&FdoExtension->TtSpinLock, &OldIrql);
1667 
1668         TtExtension->Flags |= USB2_TT_EXTENSION_FLAG_DELETED;
1669 
1670         if (IsListEmpty(&TtExtension->EndpointList))
1671         {
1672             USBPORT_UpdateAllocatedBwTt(TtExtension);
1673 
1674             for (ix = 0; ix < USB2_FRAMES; ix++)
1675             {
1676                 FdoExtension->Bandwidth[ix] += TtExtension->MaxBandwidth;
1677             }
1678 
1679             DPRINT("USBPORT_RemoveDevice: ExFreePoolWithTag TtExtension - %p\n", TtExtension);
1680             ExFreePoolWithTag(TtExtension, USB_PORT_TAG);
1681         }
1682 
1683         KeReleaseSpinLock(&FdoExtension->TtSpinLock, OldIrql);
1684     }
1685 
1686     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1687                        LOW_REALTIME_PRIORITY,
1688                        1,
1689                        FALSE);
1690 
1691     if (!(DeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB))
1692     {
1693         ExFreePoolWithTag(DeviceHandle, USB_PORT_TAG);
1694     }
1695 
1696     return STATUS_SUCCESS;
1697 }
1698 
1699 NTSTATUS
1700 NTAPI
USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)1701 USBPORT_RestoreDevice(IN PDEVICE_OBJECT FdoDevice,
1702                       IN OUT PUSBPORT_DEVICE_HANDLE OldDeviceHandle,
1703                       IN OUT PUSBPORT_DEVICE_HANDLE NewDeviceHandle)
1704 {
1705     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1706     PLIST_ENTRY iHandleList;
1707     PUSBPORT_ENDPOINT Endpoint;
1708     USBPORT_ENDPOINT_REQUIREMENTS EndpointRequirements = {0};
1709     USB_DEFAULT_PIPE_SETUP_PACKET SetupPacket;
1710     NTSTATUS Status = STATUS_SUCCESS;
1711     USBD_STATUS USBDStatus;
1712     KIRQL OldIrql;
1713     PUSBPORT_INTERFACE_HANDLE InterfaceHandle;
1714     PUSBPORT_PIPE_HANDLE PipeHandle;
1715     PUSBPORT_REGISTRATION_PACKET Packet;
1716 
1717     DPRINT("USBPORT_RestoreDevice: OldDeviceHandle - %p, NewDeviceHandle - %p\n",
1718            OldDeviceHandle,
1719            NewDeviceHandle);
1720 
1721     FdoExtension = FdoDevice->DeviceExtension;
1722 
1723     KeWaitForSingleObject(&FdoExtension->DeviceSemaphore,
1724                           Executive,
1725                           KernelMode,
1726                           FALSE,
1727                           NULL);
1728 
1729     if (!USBPORT_ValidateDeviceHandle(FdoDevice, OldDeviceHandle))
1730     {
1731         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1732                            LOW_REALTIME_PRIORITY,
1733                            1,
1734                            FALSE);
1735 
1736 #ifndef NDEBUG
1737         DPRINT("USBPORT_RestoreDevice: OldDeviceHandle not valid\n");
1738         DbgBreakPoint();
1739 #endif
1740         return STATUS_DEVICE_NOT_CONNECTED;
1741     }
1742 
1743     if (!USBPORT_ValidateDeviceHandle(FdoDevice, NewDeviceHandle))
1744     {
1745         KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1746                            LOW_REALTIME_PRIORITY,
1747                            1,
1748                            FALSE);
1749 #ifndef NDEBUG
1750         DPRINT("USBPORT_RestoreDevice: NewDeviceHandle not valid\n");
1751         DbgBreakPoint();
1752 #endif
1753         return STATUS_DEVICE_NOT_CONNECTED;
1754     }
1755 
1756     USBPORT_RemoveDeviceHandle(FdoDevice, OldDeviceHandle);
1757     USBPORT_AbortTransfers(FdoDevice, OldDeviceHandle);
1758 
1759     while (InterlockedDecrement(&OldDeviceHandle->DeviceHandleLock) >= 0)
1760     {
1761         InterlockedIncrement(&OldDeviceHandle->DeviceHandleLock);
1762         USBPORT_Wait(FdoDevice, 100);
1763     }
1764 
1765     if (sizeof(USB_DEVICE_DESCRIPTOR) == RtlCompareMemory(&NewDeviceHandle->DeviceDescriptor,
1766                                                           &OldDeviceHandle->DeviceDescriptor,
1767                                                           sizeof(USB_DEVICE_DESCRIPTOR)))
1768     {
1769         NewDeviceHandle->ConfigHandle = OldDeviceHandle->ConfigHandle;
1770 
1771         if (OldDeviceHandle->ConfigHandle)
1772         {
1773             RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1774 
1775             SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1776             SetupPacket.bRequest = USB_REQUEST_SET_CONFIGURATION;
1777             SetupPacket.wValue.W = OldDeviceHandle->ConfigHandle->ConfigurationDescriptor->bConfigurationValue;
1778             SetupPacket.wIndex.W = 0;
1779             SetupPacket.wLength = 0;
1780 
1781             USBPORT_SendSetupPacket(NewDeviceHandle,
1782                                     FdoDevice,
1783                                     &SetupPacket,
1784                                     NULL,
1785                                     0,
1786                                     NULL,
1787                                     &USBDStatus);
1788 
1789             if (USBD_ERROR(USBDStatus))
1790                 Status = USBPORT_USBDStatusToNtStatus(NULL, USBDStatus);
1791 
1792             if (NT_SUCCESS(Status))
1793             {
1794                 iHandleList = NewDeviceHandle->ConfigHandle->InterfaceHandleList.Flink;
1795 
1796                 while (iHandleList &&
1797                        iHandleList != &NewDeviceHandle->ConfigHandle->InterfaceHandleList)
1798                 {
1799                     InterfaceHandle = CONTAINING_RECORD(iHandleList,
1800                                                         USBPORT_INTERFACE_HANDLE,
1801                                                         InterfaceLink);
1802 
1803                     if (InterfaceHandle->AlternateSetting)
1804                     {
1805                         RtlZeroMemory(&SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1806 
1807                         SetupPacket.bmRequestType.Dir = BMREQUEST_HOST_TO_DEVICE;
1808                         SetupPacket.bmRequestType.Type = BMREQUEST_STANDARD;
1809                         SetupPacket.bmRequestType.Recipient = BMREQUEST_TO_INTERFACE;
1810 
1811                         SetupPacket.bRequest = USB_REQUEST_SET_INTERFACE;
1812                         SetupPacket.wValue.W = InterfaceHandle->InterfaceDescriptor.bAlternateSetting;
1813                         SetupPacket.wIndex.W = InterfaceHandle->InterfaceDescriptor.bInterfaceNumber;
1814                         SetupPacket.wLength = 0;
1815 
1816                         USBPORT_SendSetupPacket(NewDeviceHandle,
1817                                                 FdoDevice,
1818                                                 &SetupPacket,
1819                                                 NULL,
1820                                                 0,
1821                                                 NULL,
1822                                                 &USBDStatus);
1823                     }
1824 
1825                     iHandleList = iHandleList->Flink;
1826                 }
1827             }
1828         }
1829 
1830         if (NewDeviceHandle->Flags & DEVICE_HANDLE_FLAG_USB2HUB)
1831         {
1832             DPRINT1("USBPORT_RestoreDevice: FIXME Transaction Translator\n");
1833             NewDeviceHandle->TtCount = OldDeviceHandle->TtCount;
1834 
1835 #ifndef NDEBUG
1836             DbgBreakPoint();
1837 #endif
1838         }
1839 
1840         while (!IsListEmpty(&OldDeviceHandle->PipeHandleList))
1841         {
1842             PipeHandle = CONTAINING_RECORD(OldDeviceHandle->PipeHandleList.Flink,
1843                                            USBPORT_PIPE_HANDLE,
1844                                            PipeLink);
1845 
1846             DPRINT("USBPORT_RestoreDevice: PipeHandle - %p\n", PipeHandle);
1847 
1848             USBPORT_RemovePipeHandle(OldDeviceHandle, PipeHandle);
1849 
1850             if (PipeHandle != &OldDeviceHandle->PipeHandle)
1851             {
1852                 USBPORT_AddPipeHandle(NewDeviceHandle, PipeHandle);
1853 
1854                 if (!(PipeHandle->Flags & PIPE_HANDLE_FLAG_NULL_PACKET_SIZE))
1855                 {
1856                     Endpoint = PipeHandle->Endpoint;
1857                     Endpoint->DeviceHandle = NewDeviceHandle;
1858                     Endpoint->EndpointProperties.DeviceAddress = NewDeviceHandle->DeviceAddress;
1859 
1860                     Packet = &FdoExtension->MiniPortInterface->Packet;
1861 
1862                     if (!(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
1863                     {
1864                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock,
1865                                           &OldIrql);
1866 
1867                         Packet->ReopenEndpoint(FdoExtension->MiniPortExt,
1868                                                &Endpoint->EndpointProperties,
1869                                                Endpoint + 1);
1870 
1871                         Packet->SetEndpointDataToggle(FdoExtension->MiniPortExt,
1872                                                       Endpoint + 1,
1873                                                       0);
1874 
1875                         Packet->SetEndpointStatus(FdoExtension->MiniPortExt,
1876                                                   Endpoint + 1,
1877                                                   USBPORT_ENDPOINT_RUN);
1878 
1879                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1880                                           OldIrql);
1881                     }
1882                     else
1883                     {
1884                         MiniportCloseEndpoint(FdoDevice, Endpoint);
1885 
1886                         RtlZeroMemory(Endpoint + 1, Packet->MiniPortEndpointSize);
1887 
1888                         RtlZeroMemory((PVOID)Endpoint->EndpointProperties.BufferVA,
1889                                       Endpoint->EndpointProperties.BufferLength);
1890 
1891                         KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1892 
1893                         Packet->QueryEndpointRequirements(FdoExtension->MiniPortExt,
1894                                                           &Endpoint->EndpointProperties,
1895                                                           &EndpointRequirements);
1896 
1897                         KeReleaseSpinLock(&FdoExtension->MiniportSpinLock,
1898                                           OldIrql);
1899 
1900                         MiniportOpenEndpoint(FdoDevice, Endpoint);
1901 
1902                         Endpoint->Flags &= ~(ENDPOINT_FLAG_NUKE |
1903                                              ENDPOINT_FLAG_ABORTING);
1904 
1905                         KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
1906                                           &Endpoint->EndpointOldIrql);
1907 
1908                         if (Endpoint->StateLast == USBPORT_ENDPOINT_ACTIVE)
1909                         {
1910                             KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
1911 
1912                             Packet->SetEndpointState(FdoExtension->MiniPortExt,
1913                                                      Endpoint + 1,
1914                                                      USBPORT_ENDPOINT_ACTIVE);
1915 
1916                             KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
1917                         }
1918 
1919                         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1920                                           Endpoint->EndpointOldIrql);
1921                     }
1922                 }
1923             }
1924         }
1925 
1926         USBPORT_AddPipeHandle(OldDeviceHandle, &OldDeviceHandle->PipeHandle);
1927     }
1928     else
1929     {
1930 #ifndef NDEBUG
1931         DPRINT("USBPORT_RestoreDevice: New DeviceDescriptor != Old DeviceDescriptor\n");
1932         DbgBreakPoint();
1933 #endif
1934         Status = STATUS_UNSUCCESSFUL;
1935     }
1936 
1937     USBPORT_ClosePipe(OldDeviceHandle, FdoDevice, &OldDeviceHandle->PipeHandle);
1938 
1939     if (OldDeviceHandle->DeviceAddress != 0)
1940         USBPORT_FreeUsbAddress(FdoDevice, OldDeviceHandle->DeviceAddress);
1941 
1942     KeReleaseSemaphore(&FdoExtension->DeviceSemaphore,
1943                        LOW_REALTIME_PRIORITY,
1944                        1,
1945                        FALSE);
1946 
1947     ExFreePoolWithTag(OldDeviceHandle, USB_PORT_TAG);
1948 
1949     return Status;
1950 }
1951 
1952 NTSTATUS
1953 NTAPI
USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,IN ULONG TtNumber)1954 USBPORT_InitializeTT(IN PDEVICE_OBJECT FdoDevice,
1955                      IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
1956                      IN ULONG TtNumber)
1957 {
1958     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1959     PUSB2_TT_EXTENSION TtExtension;
1960     ULONG ix;
1961 
1962     DPRINT("USBPORT_InitializeTT: HubDeviceHandle - %p, TtNumber - %X\n",
1963            HubDeviceHandle,
1964            TtNumber);
1965 
1966     FdoExtension = FdoDevice->DeviceExtension;
1967 
1968     TtExtension = ExAllocatePoolWithTag(NonPagedPool,
1969                                         sizeof(USB2_TT_EXTENSION),
1970                                         USB_PORT_TAG);
1971 
1972     if (!TtExtension)
1973     {
1974         DPRINT1("USBPORT_InitializeTT: ExAllocatePoolWithTag return NULL\n");
1975         return STATUS_INSUFFICIENT_RESOURCES;
1976     }
1977 
1978     DPRINT("USBPORT_InitializeTT: TtExtension - %p\n", TtExtension);
1979 
1980     RtlZeroMemory(TtExtension, sizeof(USB2_TT_EXTENSION));
1981 
1982     TtExtension->DeviceAddress = HubDeviceHandle->DeviceAddress;
1983     TtExtension->TtNumber = TtNumber;
1984     TtExtension->RootHubPdo = FdoExtension->RootHubPdo;
1985     TtExtension->BusBandwidth = TOTAL_USB11_BUS_BANDWIDTH;
1986 
1987     InitializeListHead(&TtExtension->EndpointList);
1988 
1989     /* 90% maximum allowed for periodic endpoints */
1990     for (ix = 0; ix < USB2_FRAMES; ix++)
1991     {
1992         TtExtension->Bandwidth[ix] = TtExtension->BusBandwidth -
1993                                      TtExtension->BusBandwidth / 10;
1994     }
1995 
1996     USBPORT_UpdateAllocatedBwTt(TtExtension);
1997 
1998     for (ix = 0; ix < USB2_FRAMES; ix++)
1999     {
2000         FdoExtension->Bandwidth[ix] -= TtExtension->MaxBandwidth;
2001     }
2002 
2003     USB2_InitTT(FdoExtension->Usb2Extension, &TtExtension->Tt);
2004 
2005     InsertTailList(&HubDeviceHandle->TtList, &TtExtension->Link);
2006 
2007     return STATUS_SUCCESS;
2008 }
2009 
2010 NTSTATUS
2011 NTAPI
USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,IN ULONG TtCount)2012 USBPORT_Initialize20Hub(IN PDEVICE_OBJECT FdoDevice,
2013                         IN PUSBPORT_DEVICE_HANDLE HubDeviceHandle,
2014                         IN ULONG TtCount)
2015 {
2016     NTSTATUS Status;
2017     ULONG ix;
2018 
2019     DPRINT("USBPORT_Initialize20Hub: TtCount - %X\n", TtCount);
2020 
2021     if (!HubDeviceHandle)
2022     {
2023         return STATUS_INVALID_PARAMETER;
2024     }
2025 
2026     if (HubDeviceHandle->Flags & DEVICE_HANDLE_FLAG_ROOTHUB)
2027     {
2028         return STATUS_SUCCESS;
2029     }
2030 
2031     if (TtCount == 0)
2032     {
2033         HubDeviceHandle->TtCount = 0;
2034         return STATUS_SUCCESS;
2035     }
2036 
2037     for (ix = 0; ix < TtCount; ++ix)
2038     {
2039         Status = USBPORT_InitializeTT(FdoDevice, HubDeviceHandle, ix + 1);
2040 
2041         if (!NT_SUCCESS(Status))
2042             break;
2043     }
2044 
2045     HubDeviceHandle->TtCount = TtCount;
2046 
2047     return Status;
2048 }
2049