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