diff --git a/drivers/usb/usbehci_new/hub_controller.cpp b/drivers/usb/usbehci_new/hub_controller.cpp index cac97746a13..532efe5532b 100644 --- a/drivers/usb/usbehci_new/hub_controller.cpp +++ b/drivers/usb/usbehci_new/hub_controller.cpp @@ -65,6 +65,7 @@ public: NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb); + NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb); NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb); friend VOID StatusChangeEndpointCallBack(PVOID Context); @@ -1362,6 +1363,70 @@ CHubController::HandleGetDescriptor( return Status; } +//----------------------------------------------------------------------------------------- +NTSTATUS +CHubController::HandleClassInterface( + IN OUT PIRP Irp, + IN OUT PURB Urb) +{ + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + NTSTATUS Status; + PUSBDEVICE UsbDevice; + + // + // sanity check + // + PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); + PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength); + PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); + + // + // check if this is a valid usb device handle + // + PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))); + + // + // get device + // + UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); + + + DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n"); + DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); + DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength); + DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer); + DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); + DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits); + DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request); + DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value); + DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index); + + // + // initialize setup packet + // + CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const. + CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; + CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; + CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; + CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength; + + // + // issue request + // + Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer); + + // + // assert on failure + // + PC_ASSERT(NT_SUCCESS(Status)); + + + // + // done + // + return Status; +} + //----------------------------------------------------------------------------------------- NTSTATUS CHubController::HandleDeviceControl( @@ -1419,6 +1484,9 @@ CHubController::HandleDeviceControl( case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: Status = HandleBulkOrInterruptTransfer(Irp, Urb); break; + case URB_FUNCTION_CLASS_INTERFACE: + Status = HandleClassInterface(Irp, Urb); + break; default: DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function); break; diff --git a/drivers/usb/usbehci_new/interfaces.h b/drivers/usb/usbehci_new/interfaces.h index ddb056f0cbf..be8f19783f7 100644 --- a/drivers/usb/usbehci_new/interfaces.h +++ b/drivers/usb/usbehci_new/interfaces.h @@ -785,7 +785,7 @@ DECLARE_INTERFACE_(IUSBDevice, IUnknown) // // Description: submits an irp containing an urb - virtual NTSTATUS SubmitIrp(PIRP Urb) = 0; + virtual NTSTATUS SubmitIrp(PIRP Irp) = 0; //----------------------------------------------------------------------------------------- // diff --git a/drivers/usb/usbehci_new/memory_manager.cpp b/drivers/usb/usbehci_new/memory_manager.cpp index ed5df388489..ad78c301c1d 100644 --- a/drivers/usb/usbehci_new/memory_manager.cpp +++ b/drivers/usb/usbehci_new/memory_manager.cpp @@ -136,7 +136,7 @@ CDMAMemoryManager::Allocate( // sanity checks // ASSERT(Size < PAGE_SIZE); - ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + //ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); // // align request diff --git a/drivers/usb/usbehci_new/usb_device.cpp b/drivers/usb/usbehci_new/usb_device.cpp index 154c93cea46..7ef98b818a6 100644 --- a/drivers/usb/usbehci_new/usb_device.cpp +++ b/drivers/usb/usbehci_new/usb_device.cpp @@ -483,6 +483,11 @@ CUSBDevice::CommitIrp( // Status = Request->InitializeWithIrp(m_DmaManager, Irp); + // + // mark irp as pending + // + IoMarkIrpPending(Irp); + // // now add the request // @@ -500,7 +505,7 @@ CUSBDevice::CommitIrp( // // done // - return Status; + return STATUS_PENDING; } //---------------------------------------------------------------------------------------- @@ -1199,6 +1204,16 @@ CUSBDevice::SelectInterface( // // copy pipe handle // + DPRINT1("PipeIndex %lu\n", PipeIndex); + DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress); + DPRINT1("Interval %d\n", InterfaceInfo->Pipes[PipeIndex].Interval); + DPRINT1("MaximumPacketSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize); + DPRINT1("MaximumTransferSize %d\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize); + DPRINT1("PipeFlags %d\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags); + DPRINT1("PipeType %dd\n", InterfaceInfo->Pipes[PipeIndex].PipeType); + DPRINT1("UsbEndPoint %x\n", Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress); + PC_ASSERT(Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress == InterfaceInfo->Pipes[PipeIndex].EndpointAddress); + InterfaceInfo->Pipes[PipeIndex].PipeHandle = &Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor; if (Configuration->Interfaces[InterfaceInfo->InterfaceNumber].EndPoints[PipeIndex].EndPointDescriptor.bmAttributes & (USB_ENDPOINT_TYPE_ISOCHRONOUS | USB_ENDPOINT_TYPE_INTERRUPT)) diff --git a/drivers/usb/usbehci_new/usb_request.cpp b/drivers/usb/usbehci_new/usb_request.cpp index 49003a8ebaf..02ccfbe592a 100644 --- a/drivers/usb/usbehci_new/usb_request.cpp +++ b/drivers/usb/usbehci_new/usb_request.cpp @@ -371,6 +371,8 @@ CUSBRequest::CompletionCallback( Urb->UrbHeader.Length = 0; } + DPRINT1("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x\n", this, m_Irp, NtStatusCode, UrbStatusCode); + // // FIXME: check if the transfer was split // if yes dont complete irp yet @@ -604,9 +606,9 @@ CUSBRequest::InternalGetPidDirection() EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle; // - // end point is defined in the low byte of bmAttributes + // end point is defined in the low byte of bEndpointAddress // - return (EndpointDescriptor->bmAttributes & USB_ENDPOINT_DIRECTION_MASK); + return (EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; } //---------------------------------------------------------------------------------------- @@ -779,8 +781,11 @@ CUSBRequest::BuildBulkTransferQueueHead( PQUEUE_HEAD * OutHead) { NTSTATUS Status; - ULONG NumTransferDescriptors, TransferBufferRounded, NumPages, Index, FailIndex; PQUEUE_HEAD QueueHead; + ULONG TransferDescriptorCount, Index; + ULONG BytesAvailable, BufferIndex; + PVOID Base; + ULONG PageOffset; // // Allocate the queue head @@ -801,38 +806,33 @@ CUSBRequest::BuildBulkTransferQueueHead( PC_ASSERT(QueueHead); // - // Determine number of transfer descriptors needed. Max size is 3 * 5 Pages - // FIXME: Do we need anything bigger? + // FIXME: support more than one descriptor // - TransferBufferRounded = ROUND_TO_PAGES(m_TransferBufferLength); - NumPages = Index = 0; - NumTransferDescriptors = 1; - while (TransferBufferRounded > 0) - { - TransferBufferRounded -= PAGE_SIZE; - NumPages++; - Index++; - if (Index == 5) - { - NumTransferDescriptors++; - Index = 0; - } - } + PC_ASSERT(m_TransferBufferLength < PAGE_SIZE * 5); + PC_ASSERT(m_TransferBufferLength); - DPRINT1("Need TransferDescriptors %x, Pages %x\n", NumTransferDescriptors, NumPages); - DPRINT1("This is the end of the line!!!!!!!!\n"); - return STATUS_NOT_IMPLEMENTED; - //FIXME: Below needs work. + TransferDescriptorCount = 1; // - // FIXME: Handle transfers greater than 5 * PAGE_SIZE * 3 + // get virtual base of mdl // - if (NumTransferDescriptors > 3) NumTransferDescriptors = 3; + Base = MmGetMdlVirtualAddress(m_TransferBufferMDL); + BytesAvailable = m_TransferBufferLength; + + PC_ASSERT(m_EndpointDescriptor); + + DPRINT1("EndPointAddress %x\n", m_EndpointDescriptor->bEndpointAddress); + DPRINT1("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)); + + DPRINT1("Request %p Base Address %p TransferBytesLength %lu\n", this, Base, BytesAvailable); + DPRINT1("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->bEndpointAddress & 0x0F); + + //PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress)); // // Allocated transfer descriptors // - for (Index = 0; Index < NumTransferDescriptors; Index++) + for (Index = 0; Index < TransferDescriptorCount; Index++) { Status = CreateDescriptor(&m_TransferDescriptors[Index]); if (!NT_SUCCESS(Status)) @@ -850,12 +850,132 @@ CUSBRequest::BuildBulkTransferQueueHead( // Free Descriptors // FIXME: Implement FreeDescriptors // - //for (FailIndex = 0; FailIndex < Index; FailIndex++) - //FreeDescriptor(m_TransferDescriptors[FailIndex]); - return Status; } + // + // sanity check + // + PC_ASSERT(BytesAvailable); + + // + // now setup transfer buffers + // + for(BufferIndex = 0; BufferIndex < 5; BufferIndex++) + { + // + // setup buffer + // + if (BufferIndex == 0) + { + // + // use physical address + // + m_TransferDescriptors[Index]->BufferPointer[0] = MmGetPhysicalAddress(Base).LowPart; + + // + // get offset within page + // + PageOffset = BYTE_OFFSET(m_TransferDescriptors[Index]->BufferPointer[0]); + + // + // check if request fills another page + // + if (PageOffset + BytesAvailable >= PAGE_SIZE) + { + // + // move to next page + // + Base = (PVOID)ROUND_TO_PAGES(Base); + + // + // increment transfer bytes + // + m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = PAGE_SIZE - PageOffset; + + // + // decrement available byte count + // + BytesAvailable -= m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer; + + DPRINT1("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex], + BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); + } + else + { + // + // request ends on the first buffer page + // + m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = BytesAvailable; + BytesAvailable = 0; + + DPRINT1("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex], + BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); + break; + } + } + else + { + // + // the following pages always start on byte zero of each page + // + PC_ASSERT(((ULONG_PTR)Base & (PAGE_SIZE-1)) == 0); + + if (BytesAvailable >= PAGE_SIZE) + { + // + // store address + // + m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart; + + // + // move to next page + // + Base = (PVOID)((ULONG_PTR)Base + PAGE_SIZE); + + // + // increment transfer descriptor bytes + // + m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += PAGE_SIZE; + + // + // decrement available byte count + // + BytesAvailable -= PAGE_SIZE; + + DPRINT1("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex], + BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); + } + else + { + PC_ASSERT(BytesAvailable); + + // + // store address + // + m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart; + + // + // increment transfer descriptor bytes + // + m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += BytesAvailable; + + // + // decrement available byte count + // + BytesAvailable -= BytesAvailable; + + // + // done + // + DPRINT1("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex], + BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable); + + break; + } + } + } + // // Go ahead and link descriptors // @@ -863,9 +983,27 @@ CUSBRequest::BuildBulkTransferQueueHead( { m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr; } - + + // + // setup direction + // + m_TransferDescriptors[Index]->Token.Bits.PIDCode = InternalGetPidDirection(); + + // + // FIXME: performance penality? + // + m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE; + + // + // FIXME need dead queue transfer descriptor? + // } + // + // all bytes should have been consumed + // + PC_ASSERT(BytesAvailable == 0); + // // Initialize the QueueHead // @@ -881,19 +1019,20 @@ CUSBRequest::BuildBulkTransferQueueHead( } QueueHead->Token.Bits.DataToggle = TRUE; - + // - // Setup descriptors + // link descriptor with queue head // - m_TransferDescriptors[0]->Token.Bits.PIDCode = InternalGetPidDirection(); - //m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer = ??? - //m_TransferDescriptors[0]->Token.Bits.DataToggle = FALSE; + QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr; - m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE; + // + // store result + // + *OutHead = QueueHead; - ASSERT(m_TransferBufferMDL); - - + // + // done + // return STATUS_SUCCESS; } @@ -1351,6 +1490,7 @@ CUSBRequest::FreeQueueHead( // // release transfer descriptors // + DPRINT1("m_TransferDescriptor[0] Length %lu\n", m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer); m_DmaManager->Release(m_TransferDescriptors[0], sizeof(QUEUE_TRANSFER_DESCRIPTOR)); m_TransferDescriptors[0] = 0; }