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_new/hub_controller.cpp?rev=51384&r1=51383&r2=51384&view=diff
==============================================================================
--- 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_new/interfaces.h?rev=51384&r1=51383&r2=51384&view=diff
==============================================================================
--- 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_new/usb_device.cpp?rev=51384&r1=51383&r2=51384&view=diff
==============================================================================
--- 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;
+}
+


Reply via email to