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