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