[USBOHCI]
[reactos.git] / drivers / usb / usbohci / hub_controller.cpp
index 9a4b844..1325a84 100644 (file)
@@ -60,6 +60,7 @@ public:
     VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
     // internal ioctl routines
     NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
@@ -69,6 +70,9 @@ public:
     NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
     NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb);
+    NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb);
 
     friend VOID StatusChangeEndpointCallBack(PVOID Context);
 
@@ -592,7 +596,7 @@ CHubController::HandlePnp(
             DeviceCapabilities->HardwareDisabled = FALSE;
             DeviceCapabilities->NoDisplayInUI = FALSE;
             DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
-            for (Index = 0; Index < PowerSystemMaximum; Index++)
+            for (Index = 1; Index < PowerSystemMaximum; Index++)
                 DeviceCapabilities->DeviceState[Index] = PowerDeviceD3;
             DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
             DeviceCapabilities->D1Latency = 0;
@@ -789,7 +793,15 @@ CHubController::HandleIsochronousTransfer(
     //
     // check if this is a valid usb device handle
     //
-    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleIsochronousTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
 
     //
     // get device
@@ -846,7 +858,15 @@ CHubController::HandleBulkOrInterruptTransfer(
     //
     // check if this is a valid usb device handle
     //
-    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleBuldOrInterruptTransfer invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
 
     //
     // get device
@@ -1056,7 +1076,15 @@ CHubController::HandleSelectConfiguration(
         //
         // check if this is a valid usb device handle
         //
-        PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+        if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+        {
+            DPRINT1("HandleSelectConfiguration invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+            //
+            // invalid device handle
+            //
+            return STATUS_DEVICE_NOT_CONNECTED;
+        }
 
         //
         // get device
@@ -1098,7 +1126,15 @@ CHubController::HandleSelectInterface(
         //
         // check if this is a valid usb device handle
         //
-        PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+        if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+        {
+            DPRINT1("HandleSelectInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+            //
+            // invalid device handle
+            //
+            return STATUS_DEVICE_NOT_CONNECTED;
+        }
 
         //
         // get device
@@ -1118,7 +1154,10 @@ CHubController::HandleGetStatusFromDevice(
     IN OUT PIRP Irp, 
     PURB Urb)
 {
-    PUSHORT Status;
+    PUSHORT DeviceStatus;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
 
     //
     // sanity checks
@@ -1126,22 +1165,62 @@ CHubController::HandleGetStatusFromDevice(
     PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
     PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
     PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
-    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL); 
 
     //
     // get status buffer
     //
-    Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
+    DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
+
+
+    if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
+    {
+        //
+        // FIXME need more flags ?
+        //
+        *DeviceStatus = USB_PORT_STATUS_CONNECT;
+        return STATUS_SUCCESS;
+    }
 
     //
-    // FIXME need more flags ?
+    // check if this is a valid usb device handle
     //
-    *Status = USB_PORT_STATUS_CONNECT;
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleGetStatusFromDevice invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+     //
+     // generate setup packet
+     //
+     CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
+     CtrlSetup.wValue.LowByte = 0;
+     CtrlSetup.wValue.HiByte = 0;
+     CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index; 
+     CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
+     CtrlSetup.bmRequestType.B = 0x80;
+
+    //
+    // submit setup packet
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
+    ASSERT(Status == STATUS_SUCCESS);
+    DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
 
     //
     // done
     //
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 //-----------------------------------------------------------------------------------------
@@ -1154,6 +1233,8 @@ CHubController::HandleClassDevice(
     PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
     ULONG PortCount, Dummy2;
     USHORT Dummy1;
+    PUSBDEVICE UsbDevice;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
 
     DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
 
@@ -1162,6 +1243,44 @@ CHubController::HandleClassDevice(
     //
     switch(Urb->UrbControlVendorClassRequest.Request)
     {
+        case USB_REQUEST_GET_STATUS:
+        {
+            //
+            // check if this is a valid usb device handle
+            //
+            if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+            {
+                DPRINT1("USB_REQUEST_GET_STATUS invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+                //
+                // invalid device handle
+                //
+                return STATUS_DEVICE_NOT_CONNECTED;
+            }
+
+            //
+            // get device
+            //
+            UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+            //
+            // generate setup packet
+            //
+            CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
+            CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
+            CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
+            CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
+            CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
+            CtrlSetup.bmRequestType.B = 0xA0;
+
+            //
+            // submit setup packet
+            //
+            Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
+            ASSERT(Status == STATUS_SUCCESS);
+            break;
+        }
         case USB_REQUEST_GET_DESCRIPTOR:
         {
             switch (Urb->UrbControlVendorClassRequest.Value >> 8)
@@ -1223,6 +1342,63 @@ CHubController::HandleClassDevice(
 
     return Status;
 }
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleGetDescriptorFromInterface(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    PUSBDEVICE UsbDevice;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+
+    //
+    // sanity check
+    //
+    ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
+    ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleGetDescriptorFromInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+    //
+    // generate setup packet
+    //
+    CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
+    CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
+    CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
+    CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
+    CtrlSetup.bmRequestType.B = 0x81;
+
+    //
+    // submit setup packet
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
+    ASSERT(Status == STATUS_SUCCESS);
+
+    //
+    // done
+    //
+    return Status;
+}
+
 //-----------------------------------------------------------------------------------------
 NTSTATUS
 CHubController::HandleGetDescriptor(
@@ -1264,7 +1440,15 @@ CHubController::HandleGetDescriptor(
                 //
                 // check if this is a valid usb device handle
                 //
-                PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+                if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+                {
+                    DPRINT1("HandleGetDescriptor invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+                    //
+                    // invalid device handle
+                    //
+                    return STATUS_DEVICE_NOT_CONNECTED;
+                }
 
                 //
                 // get device
@@ -1335,7 +1519,15 @@ CHubController::HandleGetDescriptor(
                 //
                 // check if this is a valid usb device handle
                 //
-                PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+                if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+                {
+                    DPRINT1("USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+                    //
+                    // invalid device handle
+                    //
+                    return STATUS_DEVICE_NOT_CONNECTED;
+                }
 
                 //
                 // get device
@@ -1377,11 +1569,18 @@ CHubController::HandleGetDescriptor(
             PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
             PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
 
-
             //
             // check if this is a valid usb device handle
             //
-            PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+            if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+            {
+                DPRINT1("USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+                //
+                // invalid device handle
+                //
+                return STATUS_DEVICE_NOT_CONNECTED;
+            }
 
             //
             // get device
@@ -1435,7 +1634,15 @@ CHubController::HandleClassEndpoint(
     //
     // check if this is a valid usb device handle
     //
-    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleClassEndpoint invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
 
     //
     // get device
@@ -1456,12 +1663,21 @@ CHubController::HandleClassEndpoint(
     //
     // initialize setup packet
     //
-    CtrlSetup.bmRequestType.B = 0xa2; //FIXME: Const.
+    CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const.
     CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
     CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
     CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
     CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
 
+    if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+    {
+        //
+        // data direction is device to host
+        //
+        CtrlSetup.bmRequestType.B |= 0x80;
+    }
+
+
     //
     // issue request
     //
@@ -1479,6 +1695,187 @@ CHubController::HandleClassEndpoint(
     return Status;
 }
 
+NTSTATUS
+CHubController::HandleSyncResetAndClearStall(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+    ULONG Type;
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get type
+    //
+    Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
+    if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS)
+    {
+        //
+        // clear stall
+        //
+        Status = HandleClearStall(Irp, Urb);
+    }
+    DPRINT1("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", Status);
+
+    //
+    // FIXME reset data toggle
+    //
+
+    //
+    // done
+    //
+    return Status;
+}
+
+NTSTATUS
+CHubController::HandleAbortPipe(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleAbortPipe invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+
+
+    //
+    // issue request
+    //
+    Status = UsbDevice->AbortPipe(EndpointDescriptor);
+    DPRINT1("URB_FUNCTION_ABORT_PIPE Status %x\n", Status);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+
+//-----------------------------------------------------------------------------------------
+NTSTATUS
+CHubController::HandleClearStall(
+    IN OUT PIRP Irp,
+    IN OUT PURB Urb)
+{
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    NTSTATUS Status;
+    PUSBDEVICE UsbDevice;
+    PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+
+
+    //
+    // sanity check
+    //
+    PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
+    PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST));
+    PC_ASSERT(Urb->UrbPipeRequest.PipeHandle);
+
+    //
+    // check if this is a valid usb device handle
+    //
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleClearStall invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    //
+    // get endpoint descriptor
+    //
+    EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle;
+
+    //
+    // get device
+    //
+    UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
+    DPRINT1("URB_FUNCTION_SYNC_CLEAR_STALL\n");
+
+    //
+    // initialize setup packet
+    //
+    CtrlSetup.bmRequestType.B = 0x02;
+    CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE;
+    CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL;
+    CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress;
+    CtrlSetup.wLength = 0;
+    CtrlSetup.wValue.W = 0;
+
+    //
+    // issue request
+    //
+    Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0);
+
+    DPRINT1("URB_FUNCTION_CLEAR_STALL Status %x\n", Status);
+
+    //
+    // done
+    //
+    return Status;
+}
+
+
 //-----------------------------------------------------------------------------------------
 NTSTATUS
 CHubController::HandleClassInterface(
@@ -1492,14 +1889,22 @@ CHubController::HandleClassInterface(
     //
     // sanity check
     //
-    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer);
-    PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
+    //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
+    //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
     PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
 
     //
     // check if this is a valid usb device handle
     //
-    PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
+    if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)))
+    {
+        DPRINT1("HandleClassInterface invalid device handle %p\n", Urb->UrbHeader.UsbdDeviceHandle);
+
+        //
+        // invalid device handle
+        //
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
 
     //
     // get device
@@ -1520,12 +1925,20 @@ CHubController::HandleClassInterface(
     //
     // initialize setup packet
     //
-    CtrlSetup.bmRequestType.B = 0xa1; //FIXME: Const.
+    CtrlSetup.bmRequestType.B = 0x21;
     CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
     CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
     CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
     CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
 
+    if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+    {
+        //
+        // data direction is device to host
+        //
+        CtrlSetup.bmRequestType.B |= 0x80;
+    }
+
     //
     // issue request
     //
@@ -1534,8 +1947,13 @@ CHubController::HandleClassInterface(
     //
     // assert on failure
     //
-    PC_ASSERT(NT_SUCCESS(Status));
-
+    if (!NT_SUCCESS(Status))
+    {
+        //
+        // display error
+        //
+        DPRINT1("URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", Urb->UrbHeader.Status);
+    }
 
     //
     // done
@@ -1579,6 +1997,19 @@ CHubController::HandleDeviceControl(
 
             switch (Urb->UrbHeader.Function)
             {
+                case URB_FUNCTION_SYNC_RESET_PIPE:
+                case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL:
+                    Status = HandleSyncResetAndClearStall(Irp, Urb);
+                    break;
+                case URB_FUNCTION_ABORT_PIPE:
+                    Status = HandleAbortPipe(Irp, Urb);
+                    break;
+                case URB_FUNCTION_SYNC_CLEAR_STALL:
+                    Status = HandleClearStall(Irp, Urb);
+                    break;
+                case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
+                    Status = HandleGetDescriptorFromInterface(Irp, Urb);
+                    break;
                 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
                     Status = HandleGetDescriptor(Irp, Urb);
                     break;
@@ -2045,7 +2476,7 @@ USBHI_CreateUsbDevice(
     CHubController * Controller;
     NTSTATUS Status;
 
-    DPRINT1("USBHI_CreateUsbDevice\n");
+    DPRINT1("USBHI_CreateUsbDevice PortStatus %x\n", PortStatus);
 
     //
     // first get hub controller
@@ -3161,7 +3592,7 @@ CHubController::SetDeviceInterface(
     //
     // done
     //
-    return Status;
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS