Author: janderwald
Date: Sun Apr 17 19:23:13 2011
New Revision: 51384
URL:
http://svn.reactos.org/svn/reactos?rev=51384&view=rev
Log:
[USBEHCI_NEW]
- Setup a default device descriptor for the root hub and initialize it with vendor &
product id
- Partly implement URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE, URB_FUNCTION_CLASS_DEVICE
- based on mjmartin usbehci
Modified:
branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1]
(original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hub_controller.cpp [iso-8859-1] Sun Apr
17 19:23:13 2011
@@ -54,6 +54,8 @@
NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice);
NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice);
VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
+ NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
+ NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
// constructor / destructor
CHubController(IUnknown *OuterUnknown){}
@@ -65,7 +67,6 @@
PUSBHARDWAREDEVICE m_Hardware;
BOOLEAN m_IsRootHubDevice;
ULONG m_DeviceAddress;
- ULONG m_PDODeviceNumber;
BOOLEAN m_InterfaceEnabled;
UNICODE_STRING m_HubDeviceInterfaceString;
PDEVICE_OBJECT m_HubControllerDeviceObject;
@@ -74,6 +75,7 @@
PVOID m_HubCallbackContext;
PRH_INIT_CALLBACK m_HubCallbackRoutine;
+ USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
KSPIN_LOCK m_Lock;
RTL_BITMAP m_DeviceAddressBitmap;
@@ -87,6 +89,64 @@
PUSBDEVICE Device;
}USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY;
+/* Lifted from Linux with slight changes */
+const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
+{
+ 0x12, /* bLength; */
+ USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */
+ 0x00, 0x20, /* bcdUSB; v1.1 */
+ USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */
+ 0x01, /* bDeviceSubClass; */
+ 0x00, /* bDeviceProtocol; [ low/full speeds only ] */
+ 0x08, /* bMaxPacketSize0; 8 Bytes */
+ /* Fill Vendor and Product in when init root hub */
+ 0x00, 0x00, /* idVendor; */
+ 0x00, 0x00, /* idProduct; */
+ 0x00, 0x00, /* bcdDevice */
+ 0x00, /* iManufacturer; */
+ 0x00, /* iProduct; */
+ 0x00, /* iSerialNumber; */
+ 0x01 /* bNumConfigurations; */
+
+};
+
+const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
+{
+ /* one configuration */
+ 0x09, /* bLength; */
+ 0x02, /* bDescriptorType; Configuration */
+ 0x19, 0x00, /* wTotalLength; */
+ 0x01, /* bNumInterfaces; (1) */
+ 0x23, /* bConfigurationValue; */
+ 0x00, /* iConfiguration; */
+ 0x40, /* bmAttributes; */
+ 0x00 /* MaxPower; */
+};
+
+const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
+{
+ /* one interface */
+ 0x09, /* bLength: Interface; */
+ 0x04, /* bDescriptorType; Interface */
+ 0x00, /* bInterfaceNumber; */
+ 0x00, /* bAlternateSetting; */
+ 0x01, /* bNumEndpoints; */
+ 0x09, /* bInterfaceClass; HUB_CLASSCODE */
+ 0x01, /* bInterfaceSubClass; */
+ 0x00, /* bInterfaceProtocol: */
+ 0x00 /* iInterface; */
+};
+
+const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
+{
+ /* one endpoint (status change endpoint) */
+ 0x07, /* bLength; */
+ 0x05, /* bDescriptorType; Endpoint */
+ 0x81, /* bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* bmAttributes; Interrupt */
+ 0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ 0xFF /* bInterval; (255ms -- usb 2.0 spec) */
+};
//----------------------------------------------------------------------------------------
NTSTATUS
@@ -108,6 +168,8 @@
{
NTSTATUS Status;
PCOMMON_DEVICE_EXTENSION DeviceExtension;
+ USHORT VendorID, DeviceID;
+ ULONG Dummy1;
DPRINT1("CHubController::Initialize\n");
@@ -120,6 +182,7 @@
m_DeviceAddress = DeviceAddress;
m_DriverObject = DriverObject;
KeInitializeSpinLock(&m_Lock);
+ InitializeListHead(&m_UsbDeviceList);
//
// allocate device address bitmap buffer
@@ -163,6 +226,22 @@
DeviceExtension->IsFDO = FALSE;
DeviceExtension->IsHub = TRUE; //FIXME
DeviceExtension->Dispatcher = PDISPATCHIRP(this);
+
+ //
+ // intialize device descriptor
+ //
+ C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
+ RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR,
sizeof(USB_DEVICE_DESCRIPTOR));
+
+ if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID,
&Dummy1, &Dummy1)))
+ {
+ //
+ // update device descriptor
+ //
+ m_DeviceDescriptor.idVendor = VendorID;
+ m_DeviceDescriptor.idProduct = DeviceID;
+ m_DeviceDescriptor.bcdUSB = 0x200; //FIXME
+ }
//
// clear init flag
@@ -512,6 +591,174 @@
//-----------------------------------------------------------------------------------------
NTSTATUS
+CHubController::HandleClassDevice(
+ IN OUT PIRP Irp,
+ IN OUT PURB Urb)
+{
+ NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+ PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
+ ULONG PortCount, Dummy2;
+ USHORT Dummy1;
+
+ //
+ // check class request type
+ //
+ switch(Urb->UrbControlVendorClassRequest.Request)
+ {
+ case USB_DEVICE_CLASS_HUB:
+ {
+ //
+ // sanity checks
+ //
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
+ PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >=
sizeof(USB_HUB_DESCRIPTOR));
+
+ //
+ // get hub descriptor
+ //
+ UsbHubDescriptor =
(PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer;
+
+ //
+ // one hub is handled
+ //
+ UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR);
+ Urb->UrbControlVendorClassRequest.TransferBufferLength =
sizeof(USB_HUB_DESCRIPTOR);
+
+ //
+ // type should 0x29 according to msdn
+ //
+ UsbHubDescriptor->bDescriptorType = 0x29;
+
+ //
+ // get port count
+ //
+ Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1,
&PortCount, &Dummy2);
+ PC_ASSERT(Status == STATUS_SUCCESS);
+
+ //
+ // FIXME: retrieve values
+ //
+ UsbHubDescriptor->bNumberOfPorts = PortCount;
+ UsbHubDescriptor->wHubCharacteristics = 0x0012;
+ UsbHubDescriptor->bPowerOnToPowerGood = 0x01;
+ UsbHubDescriptor->bHubControlCurrent = 0x00;
+
+ //
+ // done
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ default:
+ DPRINT1("CHubController::HandleClassDevice Class %x not
implemented\n", Urb->UrbControlVendorClassRequest.Request);
+ break;
+ }
+
+ return Status;
+}
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleGetDescriptor(
+ IN OUT PIRP Irp,
+ IN OUT PURB Urb)
+{
+ NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
+ PUCHAR Buffer;
+
+ //
+ // check descriptor type
+ //
+ switch(Urb->UrbControlDescriptorRequest.DescriptorType)
+ {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ {
+ //
+ // sanity check
+ //
+ PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >=
sizeof(USB_DEVICE_DESCRIPTOR));
+
+ if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+ {
+ DPRINT1("Root Hub descriptor\n");
+ //
+ // copy root hub device descriptor
+ //
+ RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer,
&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ break;
+ }
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ {
+ //
+ // sanity checks
+ //
+ PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+ PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >=
sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+ //
+ // FIXME: support devices
+ //
+ PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
+
+ //
+ // copy configuration descriptor template
+ //
+ C_ASSERT(sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR) ==
sizeof(USB_CONFIGURATION_DESCRIPTOR));
+ RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
ROOTHUB2_CONFIGURATION_DESCRIPTOR, sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+ //
+ // get configuration descriptor, very retarded!
+ //
+ ConfigurationDescriptor =
(PUSB_CONFIGURATION_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer;
+
+ //
+ // check if buffer can hold interface and endpoint descriptor
+ //
+ if (ConfigurationDescriptor->wTotalLength >
Urb->UrbControlDescriptorRequest.TransferBufferLength)
+ {
+ //
+ // buffer too small
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ //
+ // copy interface descriptor template
+ //
+ Buffer = (PUCHAR)(ConfigurationDescriptor + 1);
+ C_ASSERT(sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR) ==
sizeof(USB_INTERFACE_DESCRIPTOR));
+ RtlCopyMemory(Buffer, ROOTHUB2_INTERFACE_DESCRIPTOR,
sizeof(USB_INTERFACE_DESCRIPTOR));
+
+ //
+ // copy end point descriptor template
+ //
+ Buffer += sizeof(USB_INTERFACE_DESCRIPTOR);
+ C_ASSERT(sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR) ==
sizeof(USB_ENDPOINT_DESCRIPTOR));
+ RtlCopyMemory(Buffer, ROOTHUB2_ENDPOINT_DESCRIPTOR,
sizeof(USB_ENDPOINT_DESCRIPTOR));
+
+ //
+ // done
+ //
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ default:
+ DPRINT1("CHubController::HandleGetDescriptor DescriptorType %x
unimplemented\n", Urb->UrbControlDescriptorRequest.DescriptorType);
+ break;
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
CHubController::HandleDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp)
@@ -553,10 +800,17 @@
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x Length %lu Status %x
Handle %p Flags %x UNIMPLEMENTED\n", Urb->UrbHeader.Function,
Urb->UrbHeader.Length, Urb->UrbHeader.Status, Urb->UrbHeader.UsbdDeviceHandle,
Urb->UrbHeader.UsbdFlags);
+ switch (Urb->UrbHeader.Function)
+ {
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ Status = HandleGetDescriptor(Irp, Urb);
+ break;
+ case URB_FUNCTION_CLASS_DEVICE:
+ Status = HandleClassDevice(Irp, Urb);
+ }
//
// request completed
//
- Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
@@ -854,7 +1108,6 @@
PUSBDEVICE UsbDevice)
{
PUSBDEVICE_ENTRY DeviceEntry;
- NTSTATUS Status;
KIRQL OldLevel;
//
@@ -1004,7 +1257,7 @@
//
// now initialize device
//
- Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller),
Controller->GetUsbHardware(),PVOID(Controller), PortNumber);
+ Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller),
Controller->GetUsbHardware(),PVOID(Controller), PortNumber, PortStatus);
//
// check for success
@@ -1359,9 +1612,8 @@
PUSB_DEVICE_INFORMATION_0 DeviceInfo;
PUSBDEVICE UsbDevice;
CHubController * Controller;
- NTSTATUS Status;
-
- DPRINT1("USBHI_QueryDeviceInformation\n");
+
+ DPRINT1("USBHI_QueryDeviceInformation %p\n", BusContext);
//
// sanity check
@@ -1382,17 +1634,54 @@
UsbDevice = (PUSBDEVICE)DeviceHandle;
PC_ASSERT(UsbDevice);
- //
- // validate device handle
- //
- if (!Controller->ValidateUsbDevice(UsbDevice))
- {
- DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n",
DeviceHandle);
-
- //
- // invalid device handle
- //
- return STATUS_DEVICE_NOT_CONNECTED;
+ if (BusContext != DeviceHandle)
+ {
+ //
+ // validate device handle
+ //
+ if (!Controller->ValidateUsbDevice(UsbDevice))
+ {
+ DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n",
DeviceHandle);
+
+ //
+ // invalid device handle
+ //
+ return STATUS_DEVICE_NOT_CONNECTED;
+ }
+
+ //
+ // access information buffer
+ //
+ DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer;
+
+ //
+ // initialize with default values
+ //
+ DeviceInfo->InformationLevel = 0;
+ DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
+ DeviceInfo->PortNumber = UsbDevice->GetPort();
+ DeviceInfo->CurrentConfigurationValue =
UsbDevice->GetConfigurationValue();
+ DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress();
+ DeviceInfo->HubAddress = 0; //FIXME
+ DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
+ DeviceInfo->DeviceType = UsbDevice->GetType();
+ DeviceInfo->NumberOfOpenPipes = 0; //FIXME
+
+ //
+ // get device descriptor
+ //
+ UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
+
+ //
+ // FIXME return pipe information
+ //
+
+ //
+ // store result length
+ //
+ *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
+
+ return STATUS_SUCCESS;
}
//
@@ -1405,18 +1694,17 @@
//
DeviceInfo->InformationLevel = 0;
DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0);
- DeviceInfo->PortNumber = UsbDevice->GetPort();
- DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue();
- DeviceInfo->DeviceAddress = 0; UsbDevice->GetDeviceAddress();
+ DeviceInfo->PortNumber = 0;
+ DeviceInfo->CurrentConfigurationValue = 0; //FIXME;
+ DeviceInfo->DeviceAddress = 0;
DeviceInfo->HubAddress = 0; //FIXME
- DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed();
- DeviceInfo->DeviceType = UsbDevice->GetType();
+ DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME
+ DeviceInfo->DeviceType = Usb20Device; //FIXME
DeviceInfo->NumberOfOpenPipes = 0; //FIXME
//
- // get device descriptor
- //
- UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor);
+ // FIXME get device descriptor
+ //
//
// FIXME return pipe information
@@ -1427,6 +1715,9 @@
//
*LengthReturned = sizeof(USB_DEVICE_INFORMATION_0);
+ //
+ // done
+ //
return STATUS_SUCCESS;
}
@@ -2077,12 +2368,7 @@
}
}
- //
- // store PDO number
- //
- //m_PDODeviceNumber = UsbDeviceNumber;
-
- DPRINT1("CreateFDO: DeviceName %wZ\n", &DeviceName);
+ DPRINT1("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName);
/* done */
return Status;
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Sun Apr 17
19:23:13 2011
@@ -344,6 +344,8 @@
};
+typedef IUSBRequest *PUSBREQUEST;
+
//=========================================================================================
//
// class IUSBQueue
@@ -398,6 +400,8 @@
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest) = 0;
};
+
+typedef IUSBQueue *PUSBQUEUE;
//=========================================================================================
//
@@ -495,7 +499,8 @@
virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController,
IN PUSBHARDWAREDEVICE Device,
IN PVOID Parent,
- IN ULONG Port) = 0;
+ IN ULONG Port,
+ IN ULONG PortStatus) = 0;
//-----------------------------------------------------------------------------------------
//
@@ -584,7 +589,7 @@
//
// Description: gets current selected configuration index
- virtual UCHAR GetConfigurationValue();
+ virtual UCHAR GetConfigurationValue() = 0;
//-----------------------------------------------------------------------------------------
//
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_device.cpp [iso-8859-1] Sun Apr 17
19:23:13 2011
@@ -11,12 +11,518 @@
#define INITGUID
#include "usbehci.h"
-
+class CUSBDevice : public IUSBDevice
+{
+public:
+ STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
+
+ STDMETHODIMP_(ULONG) AddRef()
+ {
+ InterlockedIncrement(&m_Ref);
+ return m_Ref;
+ }
+ STDMETHODIMP_(ULONG) Release()
+ {
+ InterlockedDecrement(&m_Ref);
+
+ if (!m_Ref)
+ {
+ delete this;
+ return 0;
+ }
+ return m_Ref;
+ }
+
+ // IUSBDevice interface functions
+ virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE
Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus);
+ virtual BOOLEAN IsHub();
+ virtual NTSTATUS GetParent(PVOID * Parent);
+ virtual ULONG GetDeviceAddress();
+ virtual ULONG GetPort();
+ virtual USB_DEVICE_SPEED GetSpeed();
+ virtual USB_DEVICE_TYPE GetType();
+ virtual ULONG GetState();
+ virtual void SetDeviceHandleData(PVOID Data);
+ virtual NTSTATUS SetDeviceAddress(ULONG DeviceAddress);
+ virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
+ virtual UCHAR GetConfigurationValue();
+ virtual NTSTATUS SubmitUrb(PURB Urb);
+
+ // local function
+ virtual NTSTATUS CommitUrb(PURB Urb);
+ virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN ULONG
BufferLength, IN OUT PVOID Buffer, IN OPTIONAL PIRP Irp, IN OPTIONAL PKEVENT pEvent);
+
+ // constructor / destructor
+ CUSBDevice(IUnknown *OuterUnknown){}
+ virtual ~CUSBDevice(){}
+
+protected:
+ LONG m_Ref;
+ PHUBCONTROLLER m_HubController;
+ PUSBHARDWAREDEVICE m_Device;
+ PVOID m_Parent;
+ ULONG m_Port;
+ ULONG m_DeviceAddress;
+ PVOID m_Data;
+ KSPIN_LOCK m_Lock;
+ USB_DEVICE_DESCRIPTOR m_DeviceDescriptor;
+ ULONG m_PortStatus;
+ PUSBQUEUE m_Queue;
+};
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+STDMETHODCALLTYPE
+CUSBDevice::QueryInterface(
+ IN REFIID refiid,
+ OUT PVOID* Output)
+{
+ return STATUS_UNSUCCESSFUL;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::Initialize(
+ IN PHUBCONTROLLER HubController,
+ IN PUSBHARDWAREDEVICE Device,
+ IN PVOID Parent,
+ IN ULONG Port,
+ IN ULONG PortStatus)
+{
+ NTSTATUS Status;
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+
+ //
+ // initialize members
+ //
+ m_HubController = HubController;
+ m_Device = Device;
+ m_Parent = Parent;
+ m_Port = Port;
+ m_PortStatus = PortStatus;
+
+ //
+ // initialize device lock
+ //
+ KeInitializeSpinLock(&m_Lock);
+
+ //
+ // no device address has been set yet
+ //
+ m_DeviceAddress = 0;
+
+ //
+ // get usb request queue
+ //
+ Status = m_Device->GetUSBQueue(&m_Queue);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to get usb queue
+ //
+ DPRINT1("CUSBDevice::Initialize GetUsbQueue failed with %x\n",
Status);
+ return Status;
+ }
+
+ //
+ // zero descriptor
+ //
+ RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
+ RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+ //
+ // setup request
+ //
+ CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+ CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
+ CtrlSetup.bmRequestType.B = 0x80;
+
+ //
+ // commit setup packet
+ //
+ Status = CommitSetupPacket(&CtrlSetup, sizeof(USB_DEVICE_DESCRIPTOR),
&m_DeviceDescriptor, 0, 0);
+
+ //
+ // check for success
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CUSBDevice::Initialize CommitSetupPacket failed with %x\n",
Status);
+ }
+
+ //
+ // done
+ //
+ return Status;
+}
+
+//----------------------------------------------------------------------------------------
+BOOLEAN
+CUSBDevice::IsHub()
+{
+ //
+ // USB Standard Device Class see
http://www.usb.org/developers/defined_class/#BaseClass09h
+ // for details
+ //
+ return (m_DeviceDescriptor.bDeviceClass == 0x09 &&
m_DeviceDescriptor.bDeviceSubClass == 0x00);
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::GetParent(
+ PVOID * Parent)
+{
+ //
+ // returns parent
+ //
+ *Parent = m_Parent;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetDeviceAddress()
+{
+ //
+ // get device address
+ //
+ return m_DeviceAddress;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetPort()
+{
+ //
+ // get port to which this device is connected to
+ //
+ return m_Port;
+}
+
+//----------------------------------------------------------------------------------------
+USB_DEVICE_SPEED
+CUSBDevice::GetSpeed()
+{
+ if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED)
+ {
+ //
+ // low speed device
+ //
+ return UsbLowSpeed;
+ }
+ else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED)
+ {
+ //
+ // high speed device
+ //
+ return UsbHighSpeed;
+ }
+
+ //
+ // default to full speed
+ //
+ return UsbFullSpeed;
+}
+
+//----------------------------------------------------------------------------------------
+USB_DEVICE_TYPE
+CUSBDevice::GetType()
+{
+ //
+ // device is encoded into bcdUSB
+ //
+ if (m_DeviceDescriptor.bcdUSB == 0x110)
+ {
+ //
+ // USB 1.1 device
+ //
+ return Usb11Device;
+ }
+ else if (m_DeviceDescriptor.bcdUSB == 0x200)
+ {
+ //
+ // USB 2.0 device
+ //
+ return Usb20Device;
+ }
+
+ DPRINT1("CUSBDevice::GetType Unknown bcdUSB Type %x\n",
m_DeviceDescriptor.bcdUSB);
+ PC_ASSERT(FALSE);
+
+ return Usb11Device;
+}
+
+//----------------------------------------------------------------------------------------
+ULONG
+CUSBDevice::GetState()
+{
+ UNIMPLEMENTED
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------------------
+void
+CUSBDevice::SetDeviceHandleData(
+ PVOID Data)
+{
+ //
+ // set device data, for debugging issues
+ //
+ m_Data = Data;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SetDeviceAddress(
+ ULONG DeviceAddress)
+{
+ USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+ NTSTATUS Status;
+
+ //
+ // zero request
+ //
+ RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
+
+ //
+ // initialize request
+ //
+ CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
+ CtrlSetup.wValue.W = DeviceAddress;
+
+ //
+ // set device address
+ //
+ Status = CommitSetupPacket(&CtrlSetup, 0, 0, 0, 0);
+
+ //
+ // check for success
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to set device address
+ //
+ DPRINT1("CUSBDevice::SetDeviceAddress> failed to set device address with
%x Address %x\n", Status, DeviceAddress);
+ return Status;
+ }
+
+ //
+ // store device address
+ //
+ m_DeviceAddress = DeviceAddress;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+
+//----------------------------------------------------------------------------------------
+void
+CUSBDevice::GetDeviceDescriptor(
+ PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
+{
+ RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor,
sizeof(USB_DEVICE_DESCRIPTOR));
+}
+
+//----------------------------------------------------------------------------------------
+UCHAR
+CUSBDevice::GetConfigurationValue()
+{
+ UNIMPLEMENTED
+ return 0x1;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CommitUrb(
+ PURB Urb)
+{
+ UNIMPLEMENTED
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::SubmitUrb(
+ PURB Urb)
+{
+ KIRQL OldLevel;
+ NTSTATUS Status;
+
+ //
+ // acquire device lock
+ //
+ KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+ //
+ // commit urb
+ //
+ Status = CommitUrb(Urb);
+
+ //
+ // release lock
+ //
+ KeReleaseSpinLock(&m_Lock, OldLevel);
+
+ return Status;
+}
+//----------------------------------------------------------------------------------------
+NTSTATUS
+CUSBDevice::CommitSetupPacket(
+ PUSB_DEFAULT_PIPE_SETUP_PACKET Packet,
+ IN ULONG BufferLength,
+ IN OUT PVOID Buffer,
+ IN PIRP Irp,
+ IN PKEVENT pEvent)
+{
+ NTSTATUS Status;
+ PUSBREQUEST Request;
+ KEVENT Event;
+ BOOLEAN Wait = FALSE;
+
+ if (!m_Queue)
+ {
+ //
+ // no queue, wtf?
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> no queue!!!\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // build usb request
+ //
+ Status = m_Queue->CreateUSBRequest(&Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to build request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> CreateUSBRequest failed with
%x\n", Status);
+ return Status;
+ }
+
+ //
+ // initialize request
+ //
+ Status = Request->InitializeWithSetupPacket(Packet, BufferLength, Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to initialize request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed to initialize usb request
with %x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+ //
+ // is a irp or event provided ?
+ //
+ if (Irp == NULL && pEvent == NULL)
+ {
+ //
+ // no completion details provided, requestor wants synchronized
+ //
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ pEvent = &Event;
+ Wait = TRUE;
+ }
+
+ //
+ // set completion details
+ //
+ Status = Request->SetCompletionDetails(Irp, pEvent);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to set completion details
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed to set completion details
with %x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+ //
+ // now add the request
+ //
+ Status = m_Queue->AddUSBRequest(Request);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to add request
+ //
+ DPRINT1("CUSBDevice::CommitSetupPacket> failed add request to queue with
%x\n", Status);
+ Request->Release();
+ return Status;
+ }
+
+ if (Wait)
+ {
+ //
+ // wait for the operation to complete
+ //
+ KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, NULL);
+ }
+
+ //TODO:
+ // Get result code from operation
+ //
+
+ //
+ // returns the result code when the operation has been finished
+ //
+ //Status = Request->GetResultCode();
+
+ //
+ // release request
+ //
+ Request->Release();
+
+ //
+ // done
+ //
+ return Status;
+}
+//----------------------------------------------------------------------------------------
NTSTATUS
CreateUSBDevice(
PUSBDEVICE *OutDevice)
{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
-}
-
+ CUSBDevice * This;
+
+ //
+ // allocate controller
+ //
+ This = new(NonPagedPool, TAG_USBEHCI) CUSBDevice(0);
+ if (!This)
+ {
+ //
+ // failed to allocate
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // add reference count
+ //
+ This->AddRef();
+
+ //
+ // return result
+ //
+ *OutDevice = (PUSBDEVICE)This;
+
+ //
+ // done
+ //
+ return STATUS_SUCCESS;
+}
+