* FILE: drivers/usb/usbehci/fdo.c
* PURPOSE: USB EHCI device driver.
* PROGRAMMERS:
- * Michael Martin
+ * Michael Martin (mjmartin@reactos.org)
*/
/* INCLUDES *******************************************************************/
#include "usbehci.h"
#include <stdio.h>
-//#include "ntstrsafe.h"
-
-VOID NTAPI
-DeviceArrivalWorkItem(PDEVICE_OBJECT DeviceObject, PVOID Context)
-{
- PWORKITEM_DATA WorkItemData;
- PPDO_DEVICE_EXTENSION PdoDeviceExtension;
-
- WorkItemData = (PWORKITEM_DATA)Context;
- PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
-
- if (PdoDeviceExtension->CallbackRoutine)
- PdoDeviceExtension->CallbackRoutine(PdoDeviceExtension->CallbackContext);
- else
- DPRINT1("PdoDeviceExtension->CallbackRoutine is NULL!\n");
-
- IoFreeWorkItem(WorkItemData->IoWorkItem);
- ExFreePool(WorkItemData);
-}
-
VOID NTAPI
EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
/* Check for port change on this port */
if (tmp & 0x02)
{
- PWORKITEM_DATA WorkItemData = NULL;
/* Connect or Disconnect? */
if (tmp & 0x01)
{
DPRINT1("Releasing ownership to companion host controller!\n");
/* Release ownership to companion host controller */
WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)), 0x4000);
+ continue;
}
}
KeStallExecutionProcessor(30);
- DPRINT("port tmp %x\n", tmp);
/* As per USB 2.0 Specs, 9.1.2. Reset the port and clear the status change */
tmp |= 0x100 | 0x02;
tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
- DPRINT("port tmp %x\n", tmp);
- GetDeviceDescriptor(FdoDeviceExtension, 0, 0, FALSE);
PdoDeviceExtension->ChildDeviceCount++;
- WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEM_DATA));
- if (!WorkItemData) ASSERT(FALSE);
- WorkItemData->IoWorkItem = IoAllocateWorkItem(PdoDeviceExtension->DeviceObject);
- WorkItemData->PdoDeviceExtension = PdoDeviceExtension;
- IoQueueWorkItem(WorkItemData->IoWorkItem,
- (PIO_WORKITEM_ROUTINE)DeviceArrivalWorkItem,
- DelayedWorkQueue,
- WorkItemData);
+ PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT;
+ PdoDeviceExtension->Ports[i].PortChange |= USB_PORT_STATUS_CONNECT;
+
+ PdoDeviceExtension->HaltQueue = FALSE;
+ KeSetEvent(&PdoDeviceExtension->QueueDrainedEvent, 0, FALSE);
}
else
{
StartEhci(DeviceObject);
FdoDeviceExtension->DeviceState = DEVICESTARTED;
+
return STATUS_SUCCESS;
}
InitializeListHead(&PdoDeviceExtension->IrpQueue);
KeInitializeSpinLock(&PdoDeviceExtension->IrpQueueLock);
+ KeInitializeEvent(&PdoDeviceExtension->QueueDrainedEvent, SynchronizationEvent, TRUE);
+
+ ExInitializeFastMutex(&PdoDeviceExtension->ListLock);
+
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
DeviceExtension->Pdo = Pdo;
IoDetachDevice(FdoDeviceExtension->LowerDevice);
IoDeleteSymbolicLink(&SymLinkName);
IoDeleteDevice(Fdo);
-
return STATUS_UNSUCCESSFUL;
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Unable to register device interface!\n");
+ ASSERT(FALSE);
}
else
{
Status = IoSetDeviceInterfaceState(&InterfaceSymLinkName, TRUE);
DPRINT1("SetInterfaceState %x\n", Status);
+ if (!NT_SUCCESS(Status))
+ ASSERT(FALSE);
}
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
+
+NTSTATUS NTAPI
+FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+ PIO_STACK_LOCATION Stack = NULL;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ ULONG_PTR Information = 0;
+ PUSB_DEVICE UsbDevice = NULL;
+ URB *Urb;
+
+ FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+ ASSERT(FdoDeviceExtension->Common.IsFdo == TRUE);
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+
+ ASSERT(Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
+
+ Urb = (PURB) Stack->Parameters.Others.Argument1;
+ DPRINT("Header Length %d\n", Urb->UrbHeader.Length);
+ DPRINT("Header Function %d\n", Urb->UrbHeader.Function);
+
+ UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
+
+ switch (Urb->UrbHeader.Function)
+ {
+ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+ {
+ DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n");
+ break;
+ }
+ case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
+ {
+ DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
+ break;
+ }
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ {
+ switch(Urb->UrbControlDescriptorRequest.DescriptorType)
+ {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ {
+ /* FIXNME: This probably not used for FDO and should be removed? */
+ DPRINT1("USB DEVICE DESC\n");
+ break;
+ }
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ DPRINT1("USB CONFIG DESC\n");
+ case USB_STRING_DESCRIPTOR_TYPE:
+ DPRINT1("Usb String Descriptor\n");
+ {
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+ BOOLEAN ResultOk;
+
+ CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
+ CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
+ CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_DEVICE_TO_HOST;
+ CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
+ CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
+ if (Urb->UrbControlDescriptorRequest.DescriptorType == USB_STRING_DESCRIPTOR_TYPE)
+ CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
+ else
+ CtrlSetup.wIndex.W = 0;
+ CtrlSetup.wLength = Urb->UrbControlDescriptorRequest.TransferBufferLength;
+
+ ResultOk = ExecuteControlRequest(FdoDeviceExtension, &CtrlSetup, UsbDevice->Address, UsbDevice->Port,
+ Urb->UrbControlDescriptorRequest.TransferBuffer, Urb->UrbControlDescriptorRequest.TransferBufferLength);
+
+ Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
+
+ break;
+ }
+ default:
+ {
+ DPRINT1("Descriptor Type %x not supported!\n", Urb->UrbControlDescriptorRequest.DescriptorType);
+ }
+ }
+ break;
+ }
+ case URB_FUNCTION_SELECT_CONFIGURATION:
+ {
+ DPRINT1("Selecting Configuration\n");
+ DPRINT1("Urb->UrbSelectConfiguration.ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
+ break;
+ }
+ case URB_FUNCTION_CLASS_DEVICE:
+ {
+ switch (Urb->UrbControlVendorClassRequest.Request)
+ {
+ case USB_REQUEST_GET_DESCRIPTOR:
+ {
+ DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
+ DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value);
+
+ switch (Urb->UrbControlVendorClassRequest.Value >> 8)
+ {
+ case USB_DEVICE_CLASS_AUDIO:
+ {
+ DPRINT1("USB_DEVICE_CLASS_AUDIO\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_COMMUNICATIONS:
+ {
+ DPRINT1("USB_DEVICE_CLASS_COMMUNICATIONS\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_HUMAN_INTERFACE:
+ {
+ DPRINT1("USB_DEVICE_CLASS_HUMAN_INTERFACE\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_MONITOR:
+ {
+ DPRINT1("USB_DEVICE_CLASS_MONITOR\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_PHYSICAL_INTERFACE:
+ {
+ DPRINT1("USB_DEVICE_CLASS_PHYSICAL_INTERFACE\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_POWER:
+ {
+ DPRINT1("USB_DEVICE_CLASS_POWER\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_PRINTER:
+ {
+ DPRINT1("USB_DEVICE_CLASS_PRINTER\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_STORAGE:
+ {
+ DPRINT1("USB_DEVICE_CLASS_STORAGE\n");
+ break;
+ }
+ case USB_DEVICE_CLASS_RESERVED:
+ DPRINT1("Reserved!!!\n");
+ case USB_DEVICE_CLASS_HUB:
+ {
+ DPRINT1("USB_DEVICE_CLASS_HUB request\n");
+ break;
+ }
+ default:
+ {
+ DPRINT1("Unknown UrbControlVendorClassRequest Value\n");
+ }
+ }
+ break;
+ }
+ case USB_REQUEST_GET_STATUS:
+ {
+ DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+ break;
+ }
+ default:
+ {
+ DPRINT1("Unhandled URB request for class device\n");
+ //Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+ }
+ }
+ break;
+ }
+ case URB_FUNCTION_CLASS_OTHER:
+ {
+ switch (Urb->UrbControlVendorClassRequest.Request)
+ {
+ case USB_REQUEST_GET_STATUS:
+ {
+ DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+ break;
+ }
+ case USB_REQUEST_CLEAR_FEATURE:
+ {
+ DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+ Urb->UrbControlVendorClassRequest.Value);
+ switch (Urb->UrbControlVendorClassRequest.Value)
+ {
+ case C_PORT_CONNECTION:
+ DPRINT1("Clearing Connect\n");
+ break;
+ case C_PORT_RESET:
+ DPRINT1("Clearing Reset\n");
+ break;
+ default:
+ DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
+ break;
+ }
+ break;
+ }
+ case USB_REQUEST_SET_FEATURE:
+ {
+ DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+ Urb->UrbControlVendorClassRequest.Value);
+
+ switch(Urb->UrbControlVendorClassRequest.Value)
+ {
+ case PORT_RESET:
+ {
+ DPRINT1("Port reset\n");
+ break;
+ }
+ case PORT_ENABLE:
+ {
+ DPRINT1("Unhandled Set Feature\n");
+ break;
+ }
+ default:
+ {
+ DPRINT1("Unknown Set Feature!\n");
+ break;
+ }
+ }
+ break;
+ }
+ case USB_REQUEST_SET_ADDRESS:
+ {
+ DPRINT1("USB_REQUEST_SET_ADDRESS\n");
+ break;
+ }
+ case USB_REQUEST_GET_DESCRIPTOR:
+ {
+ DPRINT1("USB_REQUEST_GET_DESCRIPTOR\n");
+ break;
+ }
+ case USB_REQUEST_SET_DESCRIPTOR:
+ {
+ DPRINT1("USB_REQUEST_SET_DESCRIPTOR\n");
+ break;
+ }
+ case USB_REQUEST_GET_CONFIGURATION:
+ {
+ DPRINT1("USB_REQUEST_GET_CONFIGURATION\n");
+ break;
+ }
+ case USB_REQUEST_SET_CONFIGURATION:
+ {
+ DPRINT1("USB_REQUEST_SET_CONFIGURATION\n");
+ break;
+ }
+ case USB_REQUEST_GET_INTERFACE:
+ {
+ DPRINT1("USB_REQUEST_GET_INTERFACE\n");
+ break;
+ }
+ case USB_REQUEST_SET_INTERFACE:
+ {
+ DPRINT1("USB_REQUEST_SET_INTERFACE\n");
+ break;
+ }
+ case USB_REQUEST_SYNC_FRAME:
+ {
+ DPRINT1("USB_REQUEST_SYNC_FRAME\n");
+ break;
+ }
+ default:
+ {
+ DPRINT1("Unknown Function Class Unknown request\n");
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
+ //Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+ }
+ }
+
+ Irp->IoStatus.Information = Information;
+
+ if (Status != STATUS_PENDING)
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return Status;
+}