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