mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
[USB\USBEHCI]
- Implement ExecuteTransfer to replace SubmitTransfer. - Start implentation for BulkTransfers and needed DMA. This needs much more work to be done correctly. We will get to it. - Implement URB_FUNCTION_CLASS_INTERFACE. - Add comments. Change 3 of 3. svn path=/trunk/; revision=51327
This commit is contained in:
parent
fe97558adf
commit
35e6c5fe82
4 changed files with 592 additions and 161 deletions
|
@ -70,13 +70,17 @@ QueueURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp)
|
|||
NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||
ULONG_PTR Information = 0;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PUSB_DEVICE UsbDevice = NULL;
|
||||
PEHCI_HOST_CONTROLLER hcd;
|
||||
URB *Urb;
|
||||
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
|
||||
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
|
||||
|
||||
hcd = &FdoDeviceExtension->hcd;
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
ASSERT(Stack);
|
||||
|
||||
|
@ -105,16 +109,62 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
{
|
||||
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
||||
{
|
||||
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER UsbDevice %x\n", UsbDevice);
|
||||
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UsbDevice->ActiveInterface->InterfaceDescriptor.bNumEndpoints; i++)
|
||||
{
|
||||
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)&UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor;
|
||||
DPRINT("EndPoint %d Handle %x\n", i, &UsbDevice->ActiveInterface->EndPoints[i]->EndPointDescriptor);
|
||||
DPRINT("bmAttributes %x\n", EndPointDesc->bmAttributes);
|
||||
DPRINT("EndPoint is transfer type %x\n", EndPointDesc->bmAttributes & 0x0F);
|
||||
}
|
||||
DPRINT("UsbDevice %x, Handle %x\n", UsbDevice, Urb->UrbBulkOrInterruptTransfer.PipeHandle);
|
||||
if (&UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor != Urb->UrbBulkOrInterruptTransfer.PipeHandle)
|
||||
{
|
||||
DPRINT1("Invalid Parameter, Expected EndPointDescriptor of %x, but got %x\n", &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor, Urb->UrbBulkOrInterruptTransfer.PipeHandle);
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
DPRINT("HubDevice %x, UsbDevice %x\n", PdoDeviceExtension->UsbDevices[0], UsbDevice);
|
||||
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
|
||||
DPRINT1("USBD_TRANSFER_DIRECTION_IN\n");
|
||||
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_OUT)
|
||||
DPRINT1("USBD_TRANSFER_DIRECTION_OUT\n");
|
||||
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)
|
||||
DPRINT1("USBD_SHORT_TRANSFER_OK\n");
|
||||
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||
DPRINT("EndPoint is transfer type %x\n", EndPointDesc->bmAttributes & 0x0F);
|
||||
DPRINT("Endpoint Address %x\n", EndPointDesc->bEndpointAddress & 0x0F);
|
||||
if ((EndPointDesc->bmAttributes & 0x0F) == USB_ENDPOINT_TYPE_BULK)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
Urb->UrbBulkOrInterruptTransfer.PipeHandle,
|
||||
NULL,
|
||||
Urb->UrbBulkOrInterruptTransfer.TransferFlags,
|
||||
Urb->UrbBulkOrInterruptTransfer.TransferBuffer ?
|
||||
Urb->UrbBulkOrInterruptTransfer.TransferBuffer :
|
||||
(PVOID)Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL,
|
||||
Urb->UrbBulkOrInterruptTransfer.TransferBuffer ?
|
||||
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength : 0,
|
||||
Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Transfer Type not implemented yet!\n");
|
||||
/* FAKE IT */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (!Urb->UrbBulkOrInterruptTransfer.TransferBuffer)
|
||||
{
|
||||
DPRINT1("TransferBuffer is NULL!\n");
|
||||
ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer != NULL);
|
||||
RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
|
||||
|
||||
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
|
||||
|
@ -122,9 +172,9 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK))
|
||||
{
|
||||
LONG i;
|
||||
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
|
||||
for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
|
||||
{
|
||||
if (PdoDeviceExtension->Ports[i].PortChange)
|
||||
if (hcd->Ports[i].PortChange)
|
||||
{
|
||||
DPRINT1("Inform hub driver that port %d has changed\n", i+1);
|
||||
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
|
||||
|
@ -177,11 +227,8 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
}
|
||||
if (UsbDevice == PdoDeviceExtension->UsbDevices[0])
|
||||
{
|
||||
DPRINT1("ROOTHUB!\n");
|
||||
BufPtr = (PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer;
|
||||
|
||||
DPRINT1("Length %x\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
|
||||
|
||||
/* Copy the Device Descriptor */
|
||||
RtlCopyMemory(BufPtr, &UsbDevice->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||
DumpDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||
|
@ -193,11 +240,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
SubmitControlTransfer(&FdoDeviceExtension->hcd,
|
||||
&CtrlSetup,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer,
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength,
|
||||
Irp);
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
0,
|
||||
&CtrlSetup,
|
||||
0,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer ?
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer :
|
||||
(PVOID)Urb->UrbControlDescriptorRequest.TransferBufferMDL,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer ?
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength : 0,
|
||||
Irp);
|
||||
break;
|
||||
}
|
||||
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
|
||||
|
@ -270,12 +323,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
SubmitControlTransfer(&FdoDeviceExtension->hcd,
|
||||
&CtrlSetup,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer,
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength,
|
||||
Irp);
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
0,
|
||||
&CtrlSetup,
|
||||
0,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer ?
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer :
|
||||
(PVOID)Urb->UrbControlDescriptorRequest.TransferBufferMDL,
|
||||
Urb->UrbControlDescriptorRequest.TransferBuffer ?
|
||||
Urb->UrbControlDescriptorRequest.TransferBufferLength : 0,
|
||||
Irp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -290,17 +348,17 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
|
||||
LONG iCount, pCount;
|
||||
|
||||
DPRINT1("Selecting Configuration\n");
|
||||
DPRINT1("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
|
||||
DPRINT("Selecting Configuration\n");
|
||||
DPRINT("ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
|
||||
|
||||
if (Urb->UrbSelectConfiguration.ConfigurationDescriptor)
|
||||
{
|
||||
Urb->UrbSelectConfiguration.ConfigurationHandle = &UsbDevice->ActiveConfig->ConfigurationDescriptor;
|
||||
DPRINT1("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
|
||||
ASSERT(FALSE);
|
||||
DPRINT("ConfigHandle %x\n", Urb->UrbSelectConfiguration.ConfigurationHandle);
|
||||
InterfaceInfo = &Urb->UrbSelectConfiguration.Interface;
|
||||
|
||||
DPRINT1("Length %x\n", InterfaceInfo->Length);
|
||||
DPRINT1("NumberOfPipes %x\n", InterfaceInfo->NumberOfPipes);
|
||||
DPRINT("Length %x\n", InterfaceInfo->Length);
|
||||
DPRINT("NumberOfPipes %x\n", InterfaceInfo->NumberOfPipes);
|
||||
|
||||
for (iCount = 0; iCount < Urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; iCount++)
|
||||
{
|
||||
|
@ -324,6 +382,29 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
|
||||
if (InterfaceInfo->Length == 0) break;
|
||||
}
|
||||
|
||||
if (UsbDevice != PdoDeviceExtension->UsbDevices[0])
|
||||
{
|
||||
DPRINT("Setting Configuration!\n");
|
||||
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
DPRINT1("Input Buffer %x, MDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, (PVOID)Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
|
||||
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
0,
|
||||
&CtrlSetup,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
Irp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Hub only has one configuration.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -334,7 +415,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
}
|
||||
case URB_FUNCTION_SELECT_INTERFACE:
|
||||
{
|
||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
|
||||
int i;
|
||||
|
||||
|
@ -353,12 +433,14 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
BuildSetupPacketFromURB(&FdoDeviceExtension->hcd, Urb, &CtrlSetup);
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
SubmitControlTransfer(&FdoDeviceExtension->hcd,
|
||||
&CtrlSetup,
|
||||
NULL,
|
||||
0,
|
||||
Irp);
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
0,
|
||||
&CtrlSetup,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
Irp);
|
||||
break;
|
||||
}
|
||||
case URB_FUNCTION_CLASS_DEVICE:
|
||||
|
@ -425,7 +507,6 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Handle this correctly */
|
||||
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
|
||||
UsbHubDescr->bDescriptorType = 0x29;
|
||||
break;
|
||||
|
@ -433,7 +514,7 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
DPRINT1("USB_DEVICE_CLASS_HUB request\n");
|
||||
UsbHubDescr->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
|
||||
UsbHubDescr->bDescriptorType = 0x29;
|
||||
UsbHubDescr->bNumberOfPorts = PdoDeviceExtension->NumberOfPorts;
|
||||
UsbHubDescr->bNumberOfPorts = hcd->ECHICaps.HCSParams.PortCount;
|
||||
UsbHubDescr->wHubCharacteristics = 0x0012;
|
||||
UsbHubDescr->bPowerOnToPowerGood = 0x01;
|
||||
UsbHubDescr->bHubControlCurrent = 0x00;
|
||||
|
@ -480,10 +561,10 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
DPRINT("USB_REQUEST_GET_STATUS Port %d\n", Urb->UrbControlVendorClassRequest.Index);
|
||||
|
||||
ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer != 0);
|
||||
DPRINT("PortStatus %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
|
||||
DPRINT("PortChange %x\n", PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange);
|
||||
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
|
||||
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
|
||||
DPRINT("PortStatus %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
|
||||
DPRINT("PortChange %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange);
|
||||
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
|
||||
((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
|
||||
break;
|
||||
}
|
||||
case USB_REQUEST_CLEAR_FEATURE:
|
||||
|
@ -492,12 +573,12 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
{
|
||||
case C_PORT_CONNECTION:
|
||||
DPRINT("C_PORT_CONNECTION\n");
|
||||
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
|
||||
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
|
||||
break;
|
||||
case C_PORT_RESET:
|
||||
DPRINT("C_PORT_RESET\n");
|
||||
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
|
||||
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
|
||||
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
|
||||
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus |= USB_PORT_STATUS_ENABLE;
|
||||
break;
|
||||
default:
|
||||
DPRINT("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
|
||||
|
@ -507,46 +588,49 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
}
|
||||
case USB_REQUEST_SET_FEATURE:
|
||||
{
|
||||
DPRINT("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
|
||||
DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
|
||||
Urb->UrbControlVendorClassRequest.Value);
|
||||
|
||||
switch(Urb->UrbControlVendorClassRequest.Value)
|
||||
{
|
||||
case PORT_RESET:
|
||||
{
|
||||
DPRINT("Port Reset %d\n", Urb->UrbControlVendorClassRequest.Index-1);
|
||||
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
|
||||
PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus &= ~USB_PORT_STATUS_ENABLE;
|
||||
ResetPort(&FdoDeviceExtension->hcd, Urb->UrbControlVendorClassRequest.Index-1);
|
||||
DPRINT1("Port Reset %d\n", Urb->UrbControlVendorClassRequest.Index-1);
|
||||
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
|
||||
hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus &= ~USB_PORT_STATUS_ENABLE;
|
||||
ResetPort(hcd, Urb->UrbControlVendorClassRequest.Index-1);
|
||||
break;
|
||||
}
|
||||
case PORT_ENABLE:
|
||||
{
|
||||
DPRINT("PORT_ENABLE not implemented\n");
|
||||
DPRINT1("PORT_ENABLE not implemented\n");
|
||||
break;
|
||||
}
|
||||
case PORT_POWER:
|
||||
{
|
||||
DPRINT("PORT_POWER not implemented\n");
|
||||
DPRINT1("PORT_POWER not implemented\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT("Unknown Set Feature!\n");
|
||||
DPRINT1("Unknown Set Feature!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(PdoDeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus & 0x8000))
|
||||
if (!(hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus & 0x8000))
|
||||
{
|
||||
DPRINT1("------ PortStatus %x\n", hcd->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus);
|
||||
DPRINT1("Calling CompletePendingURBRequest\n");
|
||||
|
||||
CompletePendingURBRequest(PdoDeviceExtension);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case USB_REQUEST_SET_ADDRESS:
|
||||
{
|
||||
DPRINT1("USB_REQUEST_SET_ADDRESS\n");
|
||||
ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
|
@ -606,7 +690,35 @@ NTSTATUS HandleUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp)
|
|||
}
|
||||
case URB_FUNCTION_CLASS_INTERFACE:
|
||||
{
|
||||
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||
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);
|
||||
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;
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
ExecuteTransfer(FdoDeviceExtension->DeviceObject,
|
||||
UsbDevice,
|
||||
0,
|
||||
&CtrlSetup,
|
||||
0,
|
||||
Urb->UrbControlVendorClassRequest.TransferBuffer ?
|
||||
Urb->UrbControlVendorClassRequest.TransferBuffer :
|
||||
(PVOID)Urb->UrbControlVendorClassRequest.TransferBufferMDL,
|
||||
Urb->UrbControlVendorClassRequest.TransferBuffer ?
|
||||
Urb->UrbControlVendorClassRequest.TransferBufferLength : 0,
|
||||
Irp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -632,8 +744,9 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
|
|||
|
||||
if (IsListEmpty(&DeviceExtension->IrpQueue))
|
||||
{
|
||||
DPRINT1("There should have been one SCE request pending\n");
|
||||
DPRINT1("There should have been one SCE request pending. Did the usbhub driver load?\n");
|
||||
KeReleaseSpinLock(&DeviceExtension->IrpQueueLock, oldIrql);
|
||||
ASSERT(FALSE);
|
||||
return;
|
||||
}
|
||||
NextIrp = RemoveHeadList(&DeviceExtension->IrpQueue);
|
||||
|
|
|
@ -47,12 +47,8 @@ const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
|
|||
0x01, /* bNumInterfaces; (1) */
|
||||
0x23, /* bConfigurationValue; */
|
||||
0x00, /* iConfiguration; */
|
||||
0x40, /* bmAttributes;
|
||||
Bit 7: must be set,
|
||||
6: Self-powered,
|
||||
5: Remote wakeup,
|
||||
4..0: reserved */
|
||||
0x00 /* MaxPower; */
|
||||
0x40, /* bmAttributes; */
|
||||
0x00 /* MaxPower; */
|
||||
};
|
||||
|
||||
const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
|
||||
|
@ -66,7 +62,7 @@ const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
|
|||
0x09, /* bInterfaceClass; HUB_CLASSCODE */
|
||||
0x01, /* bInterfaceSubClass; */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00 /* iInterface; */
|
||||
0x00 /* iInterface; */
|
||||
};
|
||||
|
||||
const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
|
||||
|
@ -88,12 +84,14 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
PIO_STACK_LOCATION Stack = NULL;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
ULONG_PTR Information = 0;
|
||||
PEHCI_HOST_CONTROLLER hcd;
|
||||
|
||||
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||||
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
|
||||
|
||||
ASSERT(PdoDeviceExtension->Common.IsFdo == FALSE);
|
||||
|
||||
hcd = &FdoDeviceExtension->hcd;
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
|
@ -108,13 +106,18 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
|
||||
UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
|
||||
|
||||
/* If there was no device passed then this URB is for the RootHub */
|
||||
if (UsbDevice == NULL)
|
||||
UsbDevice = PdoDeviceExtension->UsbDevices[0];
|
||||
|
||||
/* Check if it is a Status Change Endpoint (SCE). The Hub Driver sends this request and miniports mark the IRP pending
|
||||
if there is no changes on any of the ports. When the DPC of miniport routine detects changes this IRP will be completed.
|
||||
Based on XEN PV Usb Drivers */
|
||||
|
||||
if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
|
||||
(UsbDevice == PdoDeviceExtension->UsbDevices[0]))
|
||||
{
|
||||
DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
|
||||
DPRINT("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
|
||||
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle != &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
|
||||
{
|
||||
DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
|
||||
|
@ -123,12 +126,23 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
/* Queue the Irp first */
|
||||
QueueURBRequest(PdoDeviceExtension, Irp);
|
||||
|
||||
/* Check if there is any connected devices */
|
||||
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
|
||||
/* Check for port changes */
|
||||
if (EnumControllerPorts(hcd) == FALSE)
|
||||
{
|
||||
if (PdoDeviceExtension->Ports[i].PortChange == 0x01)
|
||||
DPRINT("No port change\n");
|
||||
Status = STATUS_PENDING;
|
||||
IoMarkIrpPending(Irp);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we reached this point then port status has changed, so check
|
||||
which port */
|
||||
for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
|
||||
{
|
||||
if (hcd->Ports[i].PortChange == 0x01)
|
||||
{
|
||||
DPRINT1("Inform hub driver that port %d has changed\n", i+1);
|
||||
DPRINT1("On SCE request: Inform hub driver that port %d has changed\n", i+1);
|
||||
ASSERT(FALSE);
|
||||
((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
|
||||
Information = 0;
|
||||
Status = STATUS_SUCCESS;
|
||||
|
@ -143,15 +157,11 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
}
|
||||
if (Status == STATUS_SUCCESS) break;
|
||||
DPRINT1("Queueing IRP\n");
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB send to device %x\n", UsbDevice);
|
||||
}
|
||||
|
||||
Status = HandleUrbRequest(PdoDeviceExtension, Irp);
|
||||
|
||||
|
@ -186,7 +196,7 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
|
||||
{
|
||||
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
|
||||
DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
|
||||
if (Stack->Parameters.Others.Argument1)
|
||||
{
|
||||
/* Return the root hubs devicehandle */
|
||||
|
@ -202,12 +212,12 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
|
||||
{
|
||||
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
|
||||
DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
|
||||
ASSERT(Stack->Parameters.Others.Argument1 != NULL);
|
||||
if (Stack->Parameters.Others.Argument1)
|
||||
{
|
||||
/* FIXME: Determine the number of hubs between the usb device and root hub */
|
||||
DPRINT1("RootHubCount %x\n", *(PULONG)Stack->Parameters.Others.Argument1);
|
||||
/* FIXME: Determine the number of hubs between the usb device and root hub.
|
||||
For now we have at least one. */
|
||||
*(PULONG)Stack->Parameters.Others.Argument1 = 1;
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
|
@ -235,15 +245,14 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
|
||||
{
|
||||
DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO Arg1 %x, Arg2 %x\n", Stack->Parameters.Others.Argument1, Stack->Parameters.Others.Argument2);
|
||||
DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
|
||||
/* DDK documents that both the PDO and FDO are returned. However, while writing the UsbHub driver it was determine
|
||||
that this was not the case. Windows usbehci driver gives the Pdo in both Arguments. Which makes sense as upper level
|
||||
drivers should not be communicating with FDO. */
|
||||
if (Stack->Parameters.Others.Argument1)
|
||||
*(PVOID *)Stack->Parameters.Others.Argument1 = FdoDeviceExtension->Pdo;
|
||||
|
||||
/* Windows usbehci driver gives the Pdo in both Arguments. */
|
||||
if (Stack->Parameters.Others.Argument2)
|
||||
//*(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDeviceReference(FdoDeviceExtension->DeviceObject);
|
||||
*(PVOID *)Stack->Parameters.Others.Argument2 = FdoDeviceExtension->Pdo;
|
||||
|
||||
Information = 0;
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
@ -254,8 +263,6 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
DPRINT1("Ehci: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
|
||||
/* FIXME: Set Callback for safe power down */
|
||||
CallBackInfo = Stack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
DPRINT1("IdleCallback %x\n", CallBackInfo->IdleCallback);
|
||||
DPRINT1("IdleContext %x\n", CallBackInfo->IdleContext);
|
||||
|
||||
PdoDeviceExtension->IdleCallback = CallBackInfo->IdleCallback;
|
||||
PdoDeviceExtension->IdleContext = CallBackInfo->IdleContext;
|
||||
|
@ -300,6 +307,7 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
|
|||
}
|
||||
case BusQueryHardwareIDs:
|
||||
{
|
||||
/* FIXME: Build from Device Vendor and Device ID */
|
||||
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
|
||||
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
|
||||
Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
|
||||
|
@ -388,7 +396,6 @@ PdoDispatchPnp(
|
|||
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
|
||||
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
|
||||
UNICODE_STRING InterfaceSymLinkName;
|
||||
LONG i;
|
||||
|
||||
DPRINT1("Ehci: PDO StartDevice\n");
|
||||
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
@ -397,15 +404,6 @@ PdoDispatchPnp(
|
|||
/* Create the root hub */
|
||||
RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
|
||||
|
||||
for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
|
||||
{
|
||||
PdoDeviceExtension->Ports[i].PortStatus = 0x8000;
|
||||
PdoDeviceExtension->Ports[i].PortChange = 0;
|
||||
|
||||
if (!FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortPowerControl)
|
||||
PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_POWER;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
|
||||
ROOTHUB2_DEVICE_DESCRIPTOR,
|
||||
sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
|
||||
|
@ -413,7 +411,8 @@ PdoDispatchPnp(
|
|||
RootHubDevice->DeviceDescriptor.idVendor = FdoDeviceExtension->VendorId;
|
||||
RootHubDevice->DeviceDescriptor.idProduct = FdoDeviceExtension->DeviceId;
|
||||
|
||||
/* FIXME: Do something better below */
|
||||
/* Here config, interfaces and descriptors are stored. This was duplicated from XEN PV Usb Drivers implementation.
|
||||
Not sure that it is really needed as the information can be queueried from the device. */
|
||||
|
||||
RootHubDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
|
||||
sizeof(PVOID) * RootHubDevice->DeviceDescriptor.bNumConfigurations,
|
||||
|
@ -483,11 +482,11 @@ PdoDispatchPnp(
|
|||
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
|
||||
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
DPRINT1("BusRelations!!!!!\n");
|
||||
DPRINT("BusRelations!!!!!\n");
|
||||
|
||||
/* The hub driver has created the new device object and reported to pnp, as a result the pnp manager
|
||||
has resent this IRP and type, so leave the next SCE request pending until a new device arrives.
|
||||
Is there a better way to do this */
|
||||
has sent this IRP and type, so leave the next SCE request pending until a new device arrives.
|
||||
Is there a better way to do this? */
|
||||
ExAcquireFastMutex(&PdoDeviceExtension->ListLock);
|
||||
PdoDeviceExtension->HaltQueue = TRUE;
|
||||
ExReleaseFastMutex(&PdoDeviceExtension->ListLock);
|
||||
|
@ -531,7 +530,7 @@ PdoDispatchPnp(
|
|||
DeviceCapabilities->UINumber = 0;
|
||||
DeviceCapabilities->DeviceD2 = 1;
|
||||
|
||||
/* FIXME */
|
||||
/* FIXME: Verify these settings are correct */
|
||||
DeviceCapabilities->HardwareDisabled = FALSE;
|
||||
//DeviceCapabilities->NoDisplayInUI = FALSE;
|
||||
DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
|
||||
|
|
|
@ -7,9 +7,20 @@
|
|||
* Michael Martin (michael.martin@reactos.org)
|
||||
*/
|
||||
|
||||
/* All QueueHeads, Descriptors and pipe setup packets used by control transfers are allocated from common buffer.
|
||||
The routines in physmem manages this buffer. Each allocation is aligned to 32bits, which is requirement of USB 2.0. */
|
||||
|
||||
#include "transfer.h"
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
typedef struct _MAPREGISTERCALLBACKINFO
|
||||
{
|
||||
PVOID MapRegisterBase;
|
||||
KEVENT Event;
|
||||
}MAPREGISTERCALLBACKINFO, *PMAPREGISTERCALLBACKINFO;
|
||||
|
||||
/* Fills CtrlSetup parameter with values based on Urb */
|
||||
VOID
|
||||
BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup)
|
||||
{
|
||||
|
@ -76,6 +87,7 @@ BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_S
|
|||
|
||||
/* SET CONFIG */
|
||||
case URB_FUNCTION_SELECT_CONFIGURATION:
|
||||
DPRINT1("Bulding data for Select Config\n");
|
||||
CtrlSetup->bRequest = USB_REQUEST_SET_CONFIGURATION;
|
||||
CtrlSetup->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue;
|
||||
CtrlSetup->wIndex.W = 0;
|
||||
|
@ -131,18 +143,86 @@ BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd, PURB Urb, PUSB_DEFAULT_PIPE_S
|
|||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
PVOID TransferBuffer,
|
||||
ULONG TransferBufferLength,
|
||||
PIRP IrpToComplete)
|
||||
/* Build a Bulk Transfer with a max transfer of 3 descriptors which each has 5 pointers to one page of memory, paged align of course */
|
||||
PQUEUE_HEAD
|
||||
BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
ULONG DeviceAddress,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
UCHAR PidDirection,
|
||||
PMDL pMdl,
|
||||
BOOLEAN FreeMdl)
|
||||
{
|
||||
PQUEUE_HEAD QueueHead;
|
||||
PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
|
||||
ULONG MdlByteCount = MmGetMdlByteCount(pMdl);
|
||||
ULONG NeededDescriptorCount = 1;
|
||||
int i;
|
||||
|
||||
QueueHead = CreateQueueHead(hcd);
|
||||
QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
|
||||
|
||||
if (PipeHandle)
|
||||
{
|
||||
QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
|
||||
QueueHead->EndPointCharacteristics.MaximumPacketLength = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->wMaxPacketSize;
|
||||
}
|
||||
|
||||
QueueHead->FreeMdl = FreeMdl;
|
||||
QueueHead->Mdl = pMdl;
|
||||
|
||||
/* FIXME: This is totally screwed */
|
||||
/* Calculate how many descriptors would be needed to transfer this buffer */
|
||||
if (pMdl)
|
||||
{
|
||||
if (MdlByteCount < (PAGE_SIZE * 5))
|
||||
NeededDescriptorCount = 1;
|
||||
else if (MdlByteCount < (PAGE_SIZE * 10))
|
||||
NeededDescriptorCount = 2;
|
||||
else if (MdlByteCount < (PAGE_SIZE * 15))
|
||||
NeededDescriptorCount = 3;
|
||||
else
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
/* Limiter Transfers to PAGE_SIZE * 5 * 3, Three Descriptors */
|
||||
|
||||
QueueHead->NumberOfTransferDescriptors = NeededDescriptorCount;
|
||||
for (i=0; i< NeededDescriptorCount;i++)
|
||||
{
|
||||
Descriptor[i] = CreateDescriptor(hcd,
|
||||
PidDirection,
|
||||
0);
|
||||
Descriptor[i]->AlternateNextPointer = QueueHead->DeadDescriptor->PhysicalAddr;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
Descriptor[i-1]->NextDescriptor = Descriptor[i];
|
||||
Descriptor[i]->PreviousDescriptor = Descriptor[i-1];
|
||||
Descriptor[i-1]->NextPointer = Descriptor[i]->PhysicalAddr;
|
||||
}
|
||||
}
|
||||
|
||||
Descriptor[0]->Token.Bits.InterruptOnComplete = TRUE;
|
||||
|
||||
/* Save the first descriptor in the QueueHead */
|
||||
QueueHead->FirstTransferDescriptor = Descriptor[0];
|
||||
QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
|
||||
|
||||
return QueueHead;
|
||||
}
|
||||
|
||||
|
||||
/* Builds a QueueHead with 2 to 3 descriptors needed for control transfer
|
||||
2 descriptors used for and control request that doesnt return data, such as SetAddress */
|
||||
PQUEUE_HEAD
|
||||
BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
ULONG DeviceAddress,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
PMDL pMdl,
|
||||
BOOLEAN FreeMdl)
|
||||
{
|
||||
PQUEUE_HEAD QueueHead;
|
||||
PQUEUE_TRANSFER_DESCRIPTOR Descriptor[3];
|
||||
ULONG MdlPhysicalAddr;
|
||||
PKEVENT Event = NULL;
|
||||
PMDL pMdl = NULL;
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetupVA, CtrlPhysicalPA;
|
||||
|
||||
CtrlSetupVA = (PUSB_DEFAULT_PIPE_SETUP_PACKET)AllocateMemory(hcd,
|
||||
|
@ -150,57 +230,45 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
|||
(ULONG*)&CtrlPhysicalPA);
|
||||
|
||||
RtlCopyMemory(CtrlSetupVA, CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
||||
/* If no Irp then wait on completion */
|
||||
if (IrpToComplete == NULL)
|
||||
{
|
||||
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
||||
KeInitializeEvent(Event, NotificationEvent, FALSE);
|
||||
}
|
||||
|
||||
if (TransferBuffer)
|
||||
{
|
||||
/* Allocate Mdl for Buffer */
|
||||
pMdl = IoAllocateMdl(TransferBuffer,
|
||||
TransferBufferLength,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
/* Lock Physical Pages */
|
||||
MmBuildMdlForNonPagedPool(pMdl);
|
||||
//MmProbeAndLockPages(pMdl, KernelMode, IoReadAccess);
|
||||
|
||||
MdlPhysicalAddr = MmGetPhysicalAddress((PVOID)TransferBuffer).LowPart;
|
||||
}
|
||||
|
||||
QueueHead = CreateQueueHead(hcd);
|
||||
QueueHead->EndPointCharacteristics.DeviceAddress = DeviceAddress;
|
||||
if (PipeHandle)
|
||||
QueueHead->EndPointCharacteristics.EndPointNumber = ((PUSB_ENDPOINT_DESCRIPTOR)PipeHandle)->bEndpointAddress & 0x0F;
|
||||
|
||||
QueueHead->Token.Bits.DataToggle = TRUE;
|
||||
QueueHead->FreeMdl = FreeMdl;
|
||||
QueueHead->Mdl = pMdl;
|
||||
|
||||
Descriptor[0] = CreateDescriptor(hcd,
|
||||
PID_CODE_SETUP_TOKEN,
|
||||
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
|
||||
|
||||
Descriptor[0]->Token.Bits.InterruptOnComplete = FALSE;
|
||||
Descriptor[0]->Token.Bits.DataToggle = FALSE;
|
||||
|
||||
/* Save the first descriptor */
|
||||
QueueHead->TransferDescriptor = Descriptor[0];
|
||||
QueueHead->FirstTransferDescriptor = Descriptor[0];
|
||||
|
||||
if (TransferBuffer)
|
||||
if (pMdl)
|
||||
{
|
||||
Descriptor[1] = CreateDescriptor(hcd,
|
||||
PID_CODE_IN_TOKEN,
|
||||
TransferBufferLength);
|
||||
MmGetMdlByteCount(pMdl));
|
||||
|
||||
Descriptor[2] = CreateDescriptor(hcd,
|
||||
PID_CODE_OUT_TOKEN,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Descriptor[2] = CreateDescriptor(hcd,
|
||||
PID_CODE_IN_TOKEN,
|
||||
0);
|
||||
}
|
||||
|
||||
Descriptor[2] = CreateDescriptor(hcd,
|
||||
PID_CODE_OUT_TOKEN,
|
||||
0);
|
||||
|
||||
Descriptor[1]->Token.Bits.InterruptOnComplete = FALSE;
|
||||
Descriptor[2]->Token.Bits.InterruptOnComplete = TRUE;
|
||||
|
||||
/* Link the descriptors */
|
||||
|
||||
if (TransferBuffer)
|
||||
if (pMdl)
|
||||
{
|
||||
Descriptor[0]->NextDescriptor = Descriptor[1];
|
||||
Descriptor[1]->NextDescriptor = Descriptor[2];
|
||||
|
@ -213,35 +281,267 @@ SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
|||
Descriptor[2]->PreviousDescriptor = Descriptor[0];
|
||||
}
|
||||
|
||||
/* Assign the descritors buffers */
|
||||
/* Assign the descriptor buffers */
|
||||
Descriptor[0]->BufferPointer[0] = (ULONG)CtrlPhysicalPA;
|
||||
|
||||
if (TransferBuffer)
|
||||
{
|
||||
Descriptor[1]->BufferPointer[0] = MdlPhysicalAddr;
|
||||
Descriptor[0]->BufferPointerVA[0] = (ULONG)CtrlSetupVA;
|
||||
|
||||
if (pMdl)
|
||||
{
|
||||
Descriptor[0]->NextPointer = Descriptor[1]->PhysicalAddr;
|
||||
Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
|
||||
Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
|
||||
Descriptor[1]->NextPointer = Descriptor[2]->PhysicalAddr;
|
||||
Descriptor[1]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Descriptor[0]->NextPointer = Descriptor[2]->PhysicalAddr;
|
||||
Descriptor[0]->AlternateNextPointer = Descriptor[2]->PhysicalAddr;
|
||||
}
|
||||
|
||||
QueueHead->NextPointer = Descriptor[0]->PhysicalAddr;
|
||||
if (pMdl)
|
||||
QueueHead->NumberOfTransferDescriptors = 3;
|
||||
else
|
||||
QueueHead->NumberOfTransferDescriptors = 2;
|
||||
return QueueHead;
|
||||
}
|
||||
|
||||
QueueHead->IrpToComplete = IrpToComplete;
|
||||
QueueHead->MdlToFree = pMdl;
|
||||
QueueHead->Event = Event;
|
||||
|
||||
/* Link in the QueueHead */
|
||||
LinkQueueHead(hcd, QueueHead);
|
||||
IO_ALLOCATION_ACTION NTAPI MapRegisterCallBack(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID MapRegisterBase,
|
||||
PVOID Context)
|
||||
{
|
||||
PMAPREGISTERCALLBACKINFO CallBackInfo = (PMAPREGISTERCALLBACKINFO)Context;
|
||||
|
||||
CallBackInfo->MapRegisterBase = MapRegisterBase;
|
||||
|
||||
KeSetEvent(&CallBackInfo->Event, IO_NO_INCREMENT, FALSE);
|
||||
return KeepObject;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
ExecuteTransfer(PDEVICE_OBJECT DeviceObject,
|
||||
PUSB_DEVICE UsbDevice,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
ULONG TransferFlags,
|
||||
PVOID TransferBufferOrMdl,
|
||||
ULONG TransferBufferLength,
|
||||
PIRP IrpToComplete)
|
||||
{
|
||||
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
|
||||
PEHCI_HOST_CONTROLLER hcd;
|
||||
PQUEUE_HEAD QueueHead;
|
||||
PKEVENT CompleteEvent = NULL;
|
||||
PMAPREGISTERCALLBACKINFO CallBackInfo;
|
||||
LARGE_INTEGER TimeOut;
|
||||
PMDL pMdl = NULL;
|
||||
BOOLEAN FreeMdl = FALSE;
|
||||
PVOID VirtualAddressOfMdl;
|
||||
ULONG NumberOfMapRegisters;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
UCHAR EndPointType, PidDirection;
|
||||
BOOLEAN IsReadOp = TRUE;
|
||||
ULONG TransferBtyesOffset, CurrentTransferBytes;
|
||||
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
|
||||
PHYSICAL_ADDRESS PhysicalAddr;
|
||||
int i,j;
|
||||
|
||||
hcd = &((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->hcd;
|
||||
|
||||
/* If no Irp then we will need to wait on completion */
|
||||
if (IrpToComplete == NULL)
|
||||
{
|
||||
DPRINT1("Waiting For Completion %x!\n", Event);
|
||||
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
|
||||
ExFreePool(Event);
|
||||
CompleteEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
||||
KeInitializeEvent(CompleteEvent, NotificationEvent, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
CallBackInfo = ExAllocatePool(NonPagedPool, sizeof(MAPREGISTERCALLBACKINFO));
|
||||
CallBackInfo->MapRegisterBase = 0;
|
||||
|
||||
KeInitializeEvent(&CallBackInfo->Event, NotificationEvent, FALSE);
|
||||
|
||||
/* Determine EndPoint Type */
|
||||
if (!PipeHandle)
|
||||
{
|
||||
EndPointType = USB_ENDPOINT_TYPE_CONTROL;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)PipeHandle;
|
||||
EndPointType = EndPointDesc->bmAttributes & 0x0F;
|
||||
}
|
||||
|
||||
if (TransferBufferOrMdl)
|
||||
{
|
||||
/* Create MDL for Buffer */
|
||||
if (TransferBufferLength)
|
||||
{
|
||||
pMdl = IoAllocateMdl(TransferBufferOrMdl,
|
||||
TransferBufferLength,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
/* UEHCI created the MDL so it needs to free it */
|
||||
FreeMdl = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pMdl = TransferBufferOrMdl;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(pMdl);
|
||||
}
|
||||
|
||||
switch (EndPointType)
|
||||
{
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
{
|
||||
QueueHead = BuildControlTransfer(hcd,
|
||||
UsbDevice->Address,
|
||||
PipeHandle,
|
||||
CtrlSetup,
|
||||
pMdl,
|
||||
FreeMdl);
|
||||
IsReadOp = TRUE;
|
||||
break;
|
||||
}
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
{
|
||||
PidDirection = EndPointDesc->bEndpointAddress >> 7;
|
||||
if (PidDirection)
|
||||
IsReadOp = FALSE;
|
||||
|
||||
QueueHead = BuildBulkTransfer(hcd,
|
||||
UsbDevice->Address,
|
||||
PipeHandle,
|
||||
PidDirection,
|
||||
pMdl,
|
||||
FreeMdl);
|
||||
|
||||
break;
|
||||
}
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
{
|
||||
DPRINT1("Interrupt Endpoints not implemented yet!\n");
|
||||
break;
|
||||
}
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
{
|
||||
DPRINT1("Isochronous Endpoints not implemented yet!\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DPRINT1("Unknown Endpoint type!!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QueueHead->IrpToComplete = IrpToComplete;
|
||||
QueueHead->Event = CompleteEvent;
|
||||
|
||||
if (!pMdl)
|
||||
{
|
||||
ASSERT(QueueHead->NumberOfTransferDescriptors == 2);
|
||||
LinkQueueHead(hcd, QueueHead);
|
||||
if (IrpToComplete == NULL)
|
||||
{
|
||||
DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
|
||||
TimeOut.QuadPart = -10000000;
|
||||
KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
|
||||
DPRINT1("Request Completed\n");
|
||||
ExFreePool(CompleteEvent);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
//ASSERT(FALSE);
|
||||
|
||||
KeFlushIoBuffers(pMdl, IsReadOp, TRUE);
|
||||
NumberOfMapRegisters = 15;
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
hcd->pDmaAdapter->DmaOperations->AllocateAdapterChannel(hcd->pDmaAdapter,
|
||||
((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ControllerFdo,
|
||||
NumberOfMapRegisters,
|
||||
MapRegisterCallBack,
|
||||
(PVOID)CallBackInfo);
|
||||
KeLowerIrql(OldIrql);
|
||||
DPRINT1("Waiting for AdapterChannel\n");
|
||||
KeWaitForSingleObject(&CallBackInfo->Event, Suspended, KernelMode, FALSE, NULL);
|
||||
DPRINT1("Dma controller ready!\n");
|
||||
DPRINT1("Getting address for MDL %x\n", pMdl);
|
||||
|
||||
VirtualAddressOfMdl = MmGetMdlVirtualAddress(pMdl);
|
||||
|
||||
TransferBtyesOffset = 0;
|
||||
while (TransferBtyesOffset < MmGetMdlByteCount(pMdl))
|
||||
{
|
||||
CurrentTransferBytes = MmGetMdlByteCount(pMdl);
|
||||
Descriptor = QueueHead->FirstTransferDescriptor;
|
||||
if ((Descriptor->Token.Bits.PIDCode == PID_CODE_SETUP_TOKEN) && (QueueHead->NumberOfTransferDescriptors == 3))
|
||||
{
|
||||
DPRINT1("QueueHead is for endpoint 0\n");
|
||||
DPRINT1("MapRegisterBase %x\n", CallBackInfo->MapRegisterBase);
|
||||
DPRINT1("VirtualAddressOfMdl %x, TransferBytesOffset %x\n", VirtualAddressOfMdl, TransferBtyesOffset);
|
||||
Descriptor = Descriptor->NextDescriptor;
|
||||
PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
|
||||
pMdl,
|
||||
CallBackInfo->MapRegisterBase,
|
||||
(PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
|
||||
&CurrentTransferBytes,
|
||||
!IsReadOp);
|
||||
DPRINT1("BufferPointer[0] = %x\n", PhysicalAddr.LowPart);
|
||||
Descriptor->BufferPointer[0] = PhysicalAddr.LowPart;
|
||||
DPRINT1("CurrentTransferBytes %x\n", CurrentTransferBytes);
|
||||
TransferBtyesOffset += CurrentTransferBytes;
|
||||
LinkQueueHead(hcd, QueueHead);
|
||||
break;
|
||||
}
|
||||
DPRINT1("PID_CODE_SETUP_TOKEN %x, PidDirection %x, NumDesc %x\n", PID_CODE_SETUP_TOKEN, PidDirection, QueueHead->NumberOfTransferDescriptors);
|
||||
for (i=0; i<QueueHead->NumberOfTransferDescriptors; i++)
|
||||
{
|
||||
if (Descriptor->Token.Bits.PIDCode != PID_CODE_SETUP_TOKEN)
|
||||
{
|
||||
for (j=0; j<5; j++)
|
||||
{
|
||||
PhysicalAddr = hcd->pDmaAdapter->DmaOperations->MapTransfer(hcd->pDmaAdapter,
|
||||
pMdl,
|
||||
CallBackInfo->MapRegisterBase,
|
||||
(PVOID)((ULONG_PTR)VirtualAddressOfMdl + TransferBtyesOffset),
|
||||
&CurrentTransferBytes,
|
||||
!IsReadOp);
|
||||
DPRINT1("BufferPointer[%d] = %x\n", j, PhysicalAddr.LowPart);
|
||||
Descriptor->BufferPointer[j] = PhysicalAddr.LowPart;
|
||||
TransferBtyesOffset += CurrentTransferBytes;
|
||||
if (TransferBtyesOffset >= MmGetMdlByteCount(pMdl))
|
||||
break;
|
||||
}
|
||||
}
|
||||
Descriptor = Descriptor->NextDescriptor;
|
||||
}
|
||||
LinkQueueHead(hcd, QueueHead);
|
||||
break;
|
||||
}
|
||||
|
||||
if (TransferBtyesOffset < MmGetMdlByteCount(pMdl)) ASSERT(FALSE);
|
||||
if (IrpToComplete == NULL)
|
||||
{
|
||||
DPRINT1("Waiting For Completion %x!\n", CompleteEvent);
|
||||
TimeOut.QuadPart = -10000000;
|
||||
KeWaitForSingleObject(CompleteEvent, Suspended, KernelMode, FALSE, NULL);//&TimeOut);
|
||||
DPRINT1("Request Completed\n");
|
||||
ExFreePool(CompleteEvent);
|
||||
}
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
hcd->pDmaAdapter->DmaOperations->FreeMapRegisters(hcd->pDmaAdapter,
|
||||
CallBackInfo->MapRegisterBase,
|
||||
NumberOfMapRegisters);
|
||||
|
||||
hcd->pDmaAdapter->DmaOperations->FreeAdapterChannel (hcd->pDmaAdapter);
|
||||
KeLowerIrql(OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -3,18 +3,37 @@
|
|||
#include "hardware.h"
|
||||
#include "hwiface.h"
|
||||
#include "physmem.h"
|
||||
#include "usbehci.h"
|
||||
#include <usb.h>
|
||||
#include <ntddk.h>
|
||||
|
||||
BOOLEAN
|
||||
SubmitControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
PVOID TransferBuffer,
|
||||
ULONG TransferBufferLength,
|
||||
PIRP IrpToComplete);
|
||||
PQUEUE_HEAD
|
||||
BuildControlTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
ULONG DeviceAddress,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
PMDL pMdl,
|
||||
BOOLEAN FreeMdl);
|
||||
|
||||
PQUEUE_HEAD
|
||||
BuildBulkTransfer(PEHCI_HOST_CONTROLLER hcd,
|
||||
ULONG DeviceAddress,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
UCHAR PidDirection,
|
||||
PMDL pMdl,
|
||||
BOOLEAN FreeMdl);
|
||||
|
||||
VOID
|
||||
BuildSetupPacketFromURB(PEHCI_HOST_CONTROLLER hcd,
|
||||
PURB Urb,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup);
|
||||
|
||||
NTSTATUS
|
||||
ExecuteTransfer(PDEVICE_OBJECT DeviceObject,
|
||||
PUSB_DEVICE UsbDevice,
|
||||
USBD_PIPE_HANDLE PipeHandle,
|
||||
PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup,
|
||||
ULONG TransferFlags,
|
||||
PVOID TransferBufferOrMdl,
|
||||
ULONG TransferBufferLength,
|
||||
PIRP IrpToComplete);
|
||||
|
|
Loading…
Reference in a new issue