Difference between revisions of "USB Stack"

From ReactOS Wiki
Jump to: navigation, search
m (Minor grammar fixes)
(21 intermediate revisions by 12 users not shown)
Line 1: Line 1:
The USB stack is the component which provides the communication between USB devices and their respective drivers and applications. It consists of multiple files, each with a distinct function. The USB stack in ReactOS is currently extremely limited. This page documents the development of the new USB stack. Development work on a USB 3 stack is not planned at this time.
+
The [[USB]] stack is the component that provides the communication between [[USB]] devices and their respective drivers and applications. It consists of multiple files, each with a distinct function. The [[USB]] stack in [[ReactOS]] is currently limited. This page documents the development of the new [[USB]] stack. Development work on a [[USB]] 3 stack is in progress.
  
 +
'''NOTE: There is a known issue with booting [[ReactOS]] from the internal HDD with a [[USB]] storage device connected which causes ROS to lose the boot device. Until this problem is fixed or a workaround is developed, please unplug any [[USB]] storage devices during boot!'''
  
 
== Overview ==
 
== Overview ==
 
+
The goal is to develop a [[USB]] stack which:
The goal is to develop a USB stack which:
+
* is USB 1.1 2.0 compliant
* is USB 1.1 - 2.0 compliant
 
 
* uses WDM (NT 5) API
 
* uses WDM (NT 5) API
 
* is compatible with all USB devices and drivers (which adhere to the standard)
 
* is compatible with all USB devices and drivers (which adhere to the standard)
  
 
The entire stack will be fully documented and the implementation progress detailed on this page.
 
The entire stack will be fully documented and the implementation progress detailed on this page.
 
  
 
== Goals ==
 
== Goals ==
 
+
* Primary Goal: USBHID (human input devices) and storage functionality working (Alpha).
* Primary Goal: USB HID (human input devices) and storage functionality working (Alpha).
 
 
* Secondary Goal: Audio and other support added.
 
* Secondary Goal: Audio and other support added.
 
* Beyond: testing and debugging.
 
* Beyond: testing and debugging.
Line 21: Line 19:
  
 
== Status ==
 
== Status ==
 +
=== USB Core Status ===
 +
* There are 2 USB specifications for the USB 1.1 standard. Devices that are used in this standard are mice, keyboards, etc.
 +
** [[OHCI]] (Open Host Controller Interface Standard) – All transfers types are implemented (bulk, iso, control, interrupt)
 +
** [[UHCI]] (Universal Host Controller Interface Standard) – Totally missing. Though it should be do-able to use OHCI driver as a base and use [http://cgit.haiku-os.org/haiku/tree/src/add-ons/kernel/busses/usb/uhci.cpp Haiku driver]
 +
* [[EHCI]] (Enhanced Host Controller Interface) – Implemented transfer types: bulk & control. Interrupt & Isochronous transfers are not implemented. Due to the missing transfer types, devices who utilize those transfer types will not be available.
 +
* USBHUB – driver for managing port and hubs – Implementation state is unknown – Michel Martin has more information on that
  
'''2010-01-08''' - [[Michael Martin]] has started re-implementation. The plan is to start with the EHCI controller and then work up the stack. Drivers will be developed against Win2k and WinXP for starting off. Progress can be found [http://cia.vc/stats/author/mjmartin here].
+
=== USB Mass Storage Support Status ===
 
+
[http://www.eltima.com/share-usb-drive-over-network/ USB Mass Storage] is implemented in [[USBSTOR]] driver and is fully working. Tested in WinXP + [[EHCI|USBEHCI]] + [[USBSTOR]]. Mass storage support requires bulk and control transfers, which are implemented in [[EHCI|USBEHCI]].
== Outdated information ==
 
See [http://www.reactos.org/wiki/index.php?title=USB_Stack&oldid=24303#Historical_.28outdated.29_information here].
 
 
 
== Source code template ==
 
Hi,
 
 
 
This is probably a scilly suggestion, but I feel a Wiki based development is more modern than an IRC based development.
 
So here is my USB source code template, don't hesitate to fill the many holes:
 
<source lang="C">
 
 
 
 
 
/*
 
 
 
  usb.C
 
 
 
  Author: JPLR jplr@users.sourceforge.net
 
  Craeted: 2010-03-10
 
 
 
  This framework is generated by EasySYS 0.3.0
 
  This template file is copying from QuickSYS 0.3.0 written by Chunhua Liu
 
 
 
  MSDN information is used heavily in this code
 
 
 
*/
 
 
 
#include "dbghelp.h"
 
#include "usb.h"
 
 
 
//
 
// A structure representing the instance information associated with
 
// a particular device
 
//
 
 
 
typedef struct _DEVICE_EXTENSION
 
{
 
    ULONG  StateVariable;
 
 
 
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
 
  
//
+
=== HID Status ===
// Device driver routine declarations.
+
The HID framework is built on 5 drivers
//
 
  
NTSTATUS
+
* HIDUSB – this is the interface driver for the USB bus. Currently supported devices are mice. Basic keyboard support should also work currently.
DriverEntry(
+
* HIDCLASS – this is the class driver for HIDUSB and others. Functionality for mice & keyboard is implemented, though support for sending output reports is not implemented.
IN PDRIVER_OBJECT DriverObject,
+
* [[MOUHID]] – mouse function driver for USB hid standard – Fully implemented and working.
IN PUNICODE_STRING RegistryPath
+
* [[KBDHID]] – keyboard function driver for the hid standard – 90% implemented, needs KbdHid_InsertScanCodes implemented for keyboard scan code dispatching to kbdclass and led status indicator support (which requires sending output reports).
);
+
* HIDPARSE – driver for parsing report descriptors – functionality implemented for mice, keyboard support needs HidParser_TranslateUsage fully implemented for modifier state (caps lock, num lock, scroll lock).
  
NTSTATUS
+
=== What already works ===
UsbDispatchCreate(
+
* Mouse support has been tested in WinXP with ReactOS [[OHCI|USBOHCI]] + HIDUSB + HIDCLASS + [[MOUHID]] + HIDPARSE and is working. The USB + HID stack also works in ReactOS.
IN PDEVICE_OBJECT DeviceObject,
+
* Basic Keyboard support is nearly ready.
IN PIRP Irp
+
* USB Mass storage support – Needs mountmgr / partmgr driver implemented. Will also need mountvol and other missing PnP stuff. - needs a few more issues to be resolved
);
 
  
NTSTATUS
+
== See Also ==
UsbDispatchClose(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
);
 
  
NTSTATUS
+
*[[Supported USB Devices]]
UsbDispatchDeviceControl(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
);
 
  
NTSTATUS
+
*[[USB Todo]] List
UsbDispatchInternalDeviceControl(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
);
 
 
 
VOID
 
UsbUnload(
 
IN PDRIVER_OBJECT DriverObject
 
);
 
 
 
#ifdef ALLOC_PRAGMA
 
#pragma alloc_text(INIT, DriverEntry)
 
#pragma alloc_text(PAGE, UsbDispatchCreate)
 
#pragma alloc_text(PAGE, UsbDispatchClose)
 
#pragma alloc_text(PAGE, UsbDispatchDeviceControl)
 
#pragma alloc_text(PAGE, UsbDispatchInternalDeviceControl)
 
#pragma alloc_text(PAGE, UsbUnload)
 
#endif // ALLOC_PRAGMA
 
 
 
NTSTATUS
 
DriverEntry(
 
IN PDRIVER_OBJECT DriverObject,
 
IN PUNICODE_STRING RegistryPath
 
)
 
{
 
NTSTATUS status = STATUS_SUCCESS;   
 
    UNICODE_STRING ntDeviceName;
 
UNICODE_STRING dosDeviceName;
 
    PDEVICE_EXTENSION deviceExtension;
 
PDEVICE_OBJECT deviceObject = NULL;
 
BOOLEAN fSymbolicLink = FALSE;
 
 
 
KdBreakPoint();
 
 
 
    dprintf("[usb] DriverEntry: %wZ\n", RegistryPath);
 
 
 
    //
 
    // A real driver would:
 
    //
 
    //    1. Report it's resources (IoReportResourceUsage)
 
    //
 
    //    2. Attempt to locate the device(s) it supports
 
 
 
    //
 
    // OK, we've claimed our resources & found our h/w, so create
 
    // a device and initialize stuff...
 
    //
 
 
 
    RtlInitUnicodeString(&ntDeviceName, USB_DEVICE_NAME_W);
 
 
 
    //
 
    // Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
 
    // i/o requests.
 
    //
 
 
 
    status = IoCreateDevice(
 
DriverObject,
 
sizeof(DEVICE_EXTENSION), // DeviceExtensionSize
 
&ntDeviceName, // DeviceName
 
FILE_DEVICE_USB, // DeviceType
 
0, // DeviceCharacteristics
 
TRUE, // Exclusive
 
&deviceObject // [OUT]
 
);
 
 
 
    if (!NT_SUCCESS(status))
 
{
 
dprintf("[usb] IoCreateDevice = 0x%x\n", status);
 
goto __failed;
 
}
 
 
 
deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
 
 
 
//
 
// Set up synchronization objects, state info,, etc.
 
//
 
 
 
    //
 
    // Create a symbolic link that Win32 apps can specify to gain access
 
    // to this driver/device
 
    //
 
 
 
    RtlInitUnicodeString(&dosDeviceName, USB_DOS_DEVICE_NAME_W);
 
 
 
    status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName);
 
 
 
    if (!NT_SUCCESS(status))
 
    {
 
        dprintf("[usb] IoCreateSymbolicLink = 0x%x\n", status);
 
goto __failed;
 
    }
 
 
 
fSymbolicLink = TRUE;
 
 
 
    //
 
    // Create dispatch points for device control, create, close.
 
    //
 
 
 
    DriverObject->MajorFunction[IRP_MJ_CREATE]        = UsbDispatchCreate;
 
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = UsbDispatchClose;
 
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbDispatchDeviceControl;
 
    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = UsbDispatchInternalDeviceControl;
 
    DriverObject->DriverUnload                        = UsbUnload;
 
 
 
    if (NT_SUCCESS(status))
 
    return status;
 
 
 
__failed:
 
 
 
if (fSymbolicLink)
 
IoDeleteSymbolicLink(&dosDeviceName);
 
 
 
if (deviceObject)
 
IoDeleteDevice(deviceObject);
 
 
 
return status;
 
}
 
 
 
NTSTATUS
 
UsbDispatchCreate(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
)
 
{
 
NTSTATUS status = STATUS_SUCCESS;
 
 
 
    Irp->IoStatus.Information = 0;
 
 
 
dprintf("[usb] IRP_MJ_CREATE\n");
 
 
 
    Irp->IoStatus.Status = status;
 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
 
 
    return status;
 
}
 
 
 
NTSTATUS
 
UsbDispatchClose(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
)
 
{
 
NTSTATUS status = STATUS_SUCCESS;
 
 
 
    Irp->IoStatus.Information = 0;
 
 
 
dprintf("[usb] IRP_MJ_CLOSE\n");
 
 
 
    Irp->IoStatus.Status = status;
 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
 
 
    return status;
 
}
 
 
 
NTSTATUS
 
UsbDispatchDeviceControl(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
)
 
{
 
NTSTATUS status = STATUS_SUCCESS;
 
    PIO_STACK_LOCATION irpStack;
 
    PDEVICE_EXTENSION deviceExtension;
 
    PVOID ioBuf;
 
    ULONG inBufLength, outBufLength;
 
ULONG ioControlCode;
 
 
 
    irpStack = IoGetCurrentIrpStackLocation(Irp);
 
    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
 
 
    Irp->IoStatus.Information = 0;
 
 
 
    //
 
    // Get the pointer to the input/output buffer and it's length
 
    //
 
 
 
    ioBuf = Irp->AssociatedIrp.SystemBuffer;
 
    inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
 
    outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
 
    ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
 
 
 
    switch (ioControlCode)
 
    {
 
case IOCTL_XYZ :
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
 
 
    default:
 
        status = STATUS_INVALID_PARAMETER;
 
 
 
        dprintf("[usb] unknown IRP_MJ_DEVICE_CONTROL = 0x%x (%04x,%04x)\n",
 
ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode),
 
IoGetFunctionCodeFromCtlCode(ioControlCode));
 
 
 
        break;
 
}
 
 
 
    //
 
    // DON'T get cute and try to use the status field of
 
    // the irp in the return status.  That IRP IS GONE as
 
    // soon as you call IoCompleteRequest.
 
    //
 
 
 
    Irp->IoStatus.Status = status;
 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
 
 
    //
 
    // We never have pending operation so always return the status code.
 
    //
 
 
 
    return status;
 
}
 
 
 
/*
 
* USB client drivers must communicate with their devices using IOCTL requests that are delivered to the device by means
 
* of an I/O request packet (IRP) of type IRP_MJ_INTERNAL_DEVICE_CONTROL.
 
* This request must contain one of the device control codes that are defined in I/O Requests for USB Client Drivers.
 
* These device control codes are "internal" in the sense that they provide an I/O interface that a USB client driver uses to manage its device
 
* and the port to which the device is connected. User-mode applications do not have access to this I/O interface.
 
*/
 
NTSTATUS
 
UsbDispatchInternalDeviceControl(
 
IN PDEVICE_OBJECT DeviceObject,
 
IN PIRP Irp
 
)
 
{
 
NTSTATUS status = STATUS_SUCCESS;
 
    PIO_STACK_LOCATION irpStack;
 
    PDEVICE_EXTENSION deviceExtension;
 
    PVOID ioBuf;
 
    ULONG inBufLength, outBufLength;
 
ULONG ioControlCode;
 
 
 
    irpStack = IoGetCurrentIrpStackLocation(Irp);
 
    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
 
 
    Irp->IoStatus.Information = 0;
 
 
 
    //
 
    // Get the pointer to the input/output buffer and it's length
 
    //
 
 
 
    ioBuf = Irp->AssociatedIrp.SystemBuffer;
 
    inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
 
    outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
 
    ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
 
 
 
    switch (ioControlCode)
 
    {
 
case IOCTL_INTERNAL_USB_SUBMIT_URB:
 
{
 
//
 
// A client driver uses IOCTL_INTERNAL_USB_SUBMIT_URB to deliver a variable-length data structure called a USB Request Block (URB) to the device it manages.
 
// Kernel-mode client drivers perform all device-specific operations, including data transfers, by means of URBs.
 
// Each URB begins with a standard header. The Length member of the URB header specifies the size, in bytes, of the URB.
 
// The Function member, which must be one of a series of system-defined URB_FUNCTION_XXX constants, determines the type of operation that is requested.
 
// In the case of data transfers, for instance, this member indicates the type of transfer.
 
//
 
    switch (ioControlCode)
 
    {
 
    case URB_FUNCTION_SELECT_CONFIGURATION
 
    //Indicates to the host controller driver that a configuration is to be selected. If set, the URB is used with _    case URB_SELECT_CONFIGURATION as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SELECT_INTERFACE
 
    //Indicates to the host controller driver that an alternate interface setting is being selected for an interface. If set, the URB is used with _    case URB_SELECT_INTERFACE as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_ABORT_PIPE
 
    //Indicates that all outstanding requests for a pipe should be canceled. If set, the URB is used with _    case URB_PIPE_REQUEST as the data structure. This general-purpose request enables a client to cancel any pending transfers for the specified pipe. Pipe state and endpoint state are unaffected. The abort request might complete before all outstanding requests have completed. Do not assume that completion of the abort request implies that all other outstanding requests have completed.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL
 
    //This URB function is obsolete in Windows 2000 and later operating systems and is not supported by Microsoft. If you specify this function with an URB request, the request will fail and the system will report an error. In the past, this function indicated that the client was requesting sole control of the frame length for the USB bus. It was used with _    case URB_FRAME_LENGTH_CONTROL as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL
 
    //This URB function is obsolete in Windows 2000 and later operating systems and is not supported by Microsoft. If you specify this function with an URB request, the request will fail and the system will report an error. In the past, this function indicated that the client was releasing control of the frame length on the USB bus. It was used with _    case URB_FRAME_LENGTH_CONTROL as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_FRAME_LENGTH
 
    //This URB function is obsolete in Windows 2000 and later operating systems and is not supported by Microsoft. If you use this function with a URB request, the request will fail and the system will report an error. In the past, this function requested the current frame length on the USB bus. If set, the URB is used with _    case URB_GET_FRAME_LENGTH as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_FRAME_LENGTH
 
    //This URB function is obsolete in Windows 2000 and later operating systems. If you use it with a URB request, the request will fail and the system will report an error. In the past, this URB function altered the current frame length on the USB bus. It was used with _    case URB_SET_FRAME_LENGTH as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER
 
    //Requests the current frame number from the host controller driver. If set, the URB is used with _    case URB_GET_CURRENT_FRAME_NUMBER as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CONTROL_TRANSFER
 
    //Transfers data to or from a control pipe. If set, the URB is used with _    case URB_CONTROL_TRANSFER as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CONTROL_TRANSFER_EX
 
    //Transfers data to or from a control pipe without a time limit specified by a timeout value. If set, the URB is used with    case    case URB_CONTROL_TRANSFER_EX as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
 
    //Transfers data from a bulk pipe or interrupt pipe or to an bulk pipe. If set, the URB is used with _    case URB_BULK_OR_INTERRUPT_TRANSFER as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_ISOCH_TRANSFER
 
    //Transfers data to or from an isochronous pipe. If set, the URB is used with _    case URB_ISOCH_TRANSFER as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_RESET_PIPE
 
    //Resets the indicated pipe. If set, this URB is used with _    case URB_PIPE_REQUEST.
 
    //The bus driver accomplishes three tasks in response to this URB:
 
    //First, for all pipes except isochronous pipes, this URB sends a CLEAR_FEATURE request to clear the device's ENDPOINT_HALT feature.
 
    //Second, the USB bus driver resets the data toggle on the host side, as required by the USB specification. The USB device should reset the data toggle on the device side when the bus driver clears its ENDPOINT_HALT feature. Since some non-compliant devices do not support this feature, Microsoft provides the two additional URBs:    case    case URB_FUNCTION_SYNC_CLEAR_STALL and    case    case URB_FUNCTION_SYNC_RESET_PIPE. These allow client drivers to clear the ENDPOINT_HALT feature on the device, or reset the pipe on the host side, respectively, without affecting the data toggle on the host side. If the device does not reset the data toggle when it should, then the client driver can compensate for this defect by not resetting the host-side data toggle. If the data toggle is reset on the host side but not on the device side, packets will get out of sequence, and the device might drop packets.
 
    //Third, after the bus driver has successfully reset the pipe, it resumes transfers with the next queued URB.
 
    //After a pipe reset, transfers resume with the next queued URB.
 
    //It is not necessary to clear a halt condition on a default control pipe. The default control pipe must always accept setup packets, and so if it halts, the USB stack will clear the halt condition automatically. The client driver does not need to take any special action to clear the halt condition on a default pipe.
 
    //All transfers must be aborted or canceled before attempting to reset the pipe.
 
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    //This URB must be sent at PASSIVE_LEVEL.
 
    case URB_FUNCTION_SYNC_RESET_PIPE
 
    //Clears the halt condition on the host side of a pipe. If set, this URB is used with _    case URB_PIPE_REQUEST as the data structure.
 
    //This URB allows a client to clear the halted state of a pipe without resetting the data toggle and without clearing the endpoint stall condition (feature ENDPOINT_HALT). To clear a halt condition on the pipe, reset the host-side data toggle and clear a stall on the device with a single operation, use    case    case URB_FUNCTION_RESET_PIPE.
 
    //The following status codes are important and have the indicated meaning:
 
    //USBD_STATUS_INVALID_PIPE_HANDLE
 
    //The PipeHandle is not valid
 
    //USBD_STATUS_ERROR_BUSY
 
    //The endpoint has active transfers pending.
 
    //It is not necessary to clear a halt condition on a default control pipe. The default control pipe must always accept setup packets, and so if it halts, the USB stack will clear the halt condition automatically. The client driver does not need to take any special action to clear the halt condition on a default pipe.
 
    //All transfers must be aborted or canceled before attempting to reset the pipe.
 
 
    //This URB must be sent at PASSIVE_LEVEL.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SYNC_CLEAR_STALL
 
    //Clears the stall condition on the endpoint. For all pipes except isochronous pipes, this URB sends a CLEAR_FEATURE request to clear the device's ENDPOINT_HALT feature. However, unlike the    case    case URB_FUNCTION_RESET_PIPE function, this URB function does not reset the data toggle on the host side of the pipe.
 
    //The USB specification requires devices to reset the device-side data toggle after the client clears the device's ENDPOINT_HALT feature, but some non-compliant devices do not reset their data toggle properly. Client drivers that manage such devices can compensate for this defect by clearing the stall condition directly with    case    case URB_FUNCTION_SYNC_CLEAR_STALL instead of resetting the pipe with    case    case URB_FUNCTION_RESET_PIPE.    case    case URB_FUNCTION_SYNC_CLEAR_STALL clears a stall condition on the device without resetting the host-side data toggle. This prevents a non-compliant device from interpreting the next packet as a retransmission and dropping the packet.
 
    //If set, the URB is used with _    case URB_PIPE_REQUEST as the data structure.
 
 
    //This URB function should be sent at PASSIVE_LEVEL
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
 
    //Retrieves the device descriptor from a specific USB device. If set, the URB is used with _    case URB_CONTROL_DESCRIPTOR_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT
 
    //Retrieves the descriptor from an endpoint on an interface for a USB device. If set, the URB is used with _    case URB_CONTROL_DESCRIPTOR_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE
 
    //Sets a device descriptor on a device. If set, the URB is used with _    case URB_CONTROL_DESCRIPTOR_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT
 
    //Sets an endpoint descriptor on an endpoint for an interface. If set, the URB is used with _    case URB_CONTROL_DESCRIPTOR_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_FEATURE_TO_DEVICE
 
    //Sets a USB-defined feature on a device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_FEATURE_TO_INTERFACE
 
    //Sets a USB-defined feature on an interface for a device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT
 
    //Sets a USB-defined feature on an endpoint for an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_SET_FEATURE_TO_OTHER
 
    //Sets a USB-defined feature on a device-defined target on a USB device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE
 
    //Clears a USB-defined feature on a device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE
 
    //Clears a USB-defined feature on an interface for a device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT
 
    //Clears a USB-defined feature on an endpoint, for an interface, on a USB device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER
 
    //Clears a USB-defined feature on a device defined target on a USB device. If set, the URB is used with _    case URB_CONTROL_FEATURE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_STATUS_FROM_DEVICE
 
    //Retrieves status from a USB device. If set, the URB is used with _    case URB_CONTROL_GET_STATUS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_STATUS_FROM_INTERFACE
 
    //Retrieves status from an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_GET_STATUS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT
 
    //Retrieves status from an endpoint for an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_GET_STATUS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_STATUS_FROM_OTHER
 
    //Retrieves status from a device-defined target on a USB device. If set, the URB is used with _    case URB_CONTROL_GET_STATUS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_VENDOR_DEVICE
 
    //Sends a vendor-specific command to a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_VENDOR_INTERFACE
 
    //Sends a vendor-specific command for an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_VENDOR_ENDPOINT
 
    //Sends a vendor-specific command for an endpoint on an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_VENDOR_OTHER
 
    //Sends a vendor-specific command to a device-defined target on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLASS_DEVICE
 
    //Sends a USB-defined class-specific command to a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLASS_INTERFACE
 
    //Sends a USB-defined class-specific command to an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLASS_ENDPOINT
 
    //Sends a USB-defined class-specific command to an endpoint, on an interface, on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_CLASS_OTHER
 
    //Sends a USB-defined class-specific command to a device defined target on a USB device. If set, the URB is used with _    case URB_CONTROL_VENDOR_OR_CLASS_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_CONFIGURATION
 
    //Retrieves the current configuration on a USB device. If set, the URB is used with _    case URB_CONTROL_GET_CONFIGURATION_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    case URB_FUNCTION_GET_INTERFACE
 
    //Retrieves the current settings for an interface on a USB device. If set, the URB is used with _    case URB_CONTROL_GET_INTERFACE_REQUEST as the data structure.
 
{
 
//
 
// Manage this!
 
//
 
 
            break;
 
}
 
    default:
 
        status = STATUS_INVALID_PARAMETER;
 
 
        dprintf("[usb] unknown URB  = 0x%x (%04x,%04x)\n",
 
ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode),
 
IoGetFunctionCodeFromCtlCode(ioControlCode));
 
 
        break;
 
}
 
 
 
            break;
 
}
 
 
case IOCTL_INTERNAL_USB_SUBMIT_URB
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_RESET_PORT
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_PORT_STATUS
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_ENABLE_PORT
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_HUB_COUNT
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_CYCLE_PORT
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_HUB_NAME
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_BUS_INFO
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION
 
{
 
//
 
// Manage this!
 
//
 
 
 
            break;
 
}
 
 
 
    default:
 
        status = STATUS_INVALID_PARAMETER;
 
 
 
        dprintf("[usb] unknown IRP_MJ_DEVICE_CONTROL = 0x%x (%04x,%04x)\n",
 
ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode),
 
IoGetFunctionCodeFromCtlCode(ioControlCode));
 
 
 
        break;
 
}
 
 
 
    //
 
    // DON'T get cute and try to use the status field of
 
    // the irp in the return status.  That IRP IS GONE as
 
    // soon as you call IoCompleteRequest.
 
    //
 
 
 
    Irp->IoStatus.Status = status;
 
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
 
 
    //
 
    // We never have pending operation so always return the status code.
 
    //
 
 
 
    return status;
 
}
 
 
 
VOID
 
UsbUnload(
 
IN PDRIVER_OBJECT DriverObject
 
)
 
{
 
    UNICODE_STRING dosDeviceName;
 
 
 
//
 
    // Free any resources
 
    //
 
 
 
    //
 
    // Delete the symbolic link
 
    //
 
 
 
    RtlInitUnicodeString(&dosDeviceName, USB_DOS_DEVICE_NAME_W);
 
 
 
    IoDeleteSymbolicLink(&dosDeviceName);
 
 
 
    //
 
    // Delete the device object
 
    //
 
 
 
    IoDeleteDevice(DriverObject->DeviceObject);
 
 
 
    dprintf("[usb] unloaded\n");
 
}
 
 
 
</source>
 
  
 
== References ==
 
== References ==
 +
* [http://www.usb.org/developers/docs/ USB.org specifications]
 +
* [http://xenbits.xensource.com/ext/win-pvdrivers.hg XEN PV USB Drivers]
 +
* [http://msdn.microsoft.com/en-us/library/ff537858.aspx Roadmap for Developing USB Drivers]
 +
* Windows Driver Kit (Driver Development Kit)
 +
* [http://www.microsoft.com/whdc/archive/USB2support.mspx?pf=true USB Driver Stack for Windows XP and later]
 +
* [http://msdn.microsoft.com/en-us/library/ff539301.aspx USB Device Stack for Windows XP and later]
 +
* [http://www.intel.com/technology/USB/download/xHCI_Specification_for_USB.pdf USB 3.0 xHCI specifications]
  
* [http://www.usb.org/developers/docs/ USB.org specifications]
 
* [http://xenbits.xensource.com/ext/win-pvdrivers.hg XEN PV Usb Drivers]
 
* [http://msdn.microsoft.com/en-us/library/ee621942.aspx How to start USB Driver Development]
 
* Windows Driver Kit (Driver Development Kit).
 
* various books and sites on the WDM model, to be expanded later.
 
* [http://www.microsoft.com/whdc/archive/usb2support.mspx?pf=true USB Driver Stack for Windows XP and later]
 
* [http://msdn.microsoft.com/en-us/library/ms794302.aspx USB Device Stack for Windows XP and later]
 
 
[[Category:Documentation]]
 
[[Category:Documentation]]
 +
[[Category:ReactOS Components]]

Revision as of 07:59, 29 December 2019

The USB stack is the component that provides the communication between USB devices and their respective drivers and applications. It consists of multiple files, each with a distinct function. The USB stack in ReactOS is currently limited. This page documents the development of the new USB stack. Development work on a USB 3 stack is in progress.

NOTE: There is a known issue with booting ReactOS from the internal HDD with a USB storage device connected which causes ROS to lose the boot device. Until this problem is fixed or a workaround is developed, please unplug any USB storage devices during boot!

Overview

The goal is to develop a USB stack which:

  • is USB 1.1 – 2.0 compliant
  • uses WDM (NT 5) API
  • is compatible with all USB devices and drivers (which adhere to the standard)

The entire stack will be fully documented and the implementation progress detailed on this page.

Goals

  • Primary Goal: USBHID (human input devices) and storage functionality working (Alpha).
  • Secondary Goal: Audio and other support added.
  • Beyond: testing and debugging.

Due to the complexity and size, no release dates will be provided as of now.

Status

USB Core Status

  • There are 2 USB specifications for the USB 1.1 standard. Devices that are used in this standard are mice, keyboards, etc.
    • OHCI (Open Host Controller Interface Standard) – All transfers types are implemented (bulk, iso, control, interrupt)
    • UHCI (Universal Host Controller Interface Standard) – Totally missing. Though it should be do-able to use OHCI driver as a base and use Haiku driver
  • EHCI (Enhanced Host Controller Interface) – Implemented transfer types: bulk & control. Interrupt & Isochronous transfers are not implemented. Due to the missing transfer types, devices who utilize those transfer types will not be available.
  • USBHUB – driver for managing port and hubs – Implementation state is unknown – Michel Martin has more information on that

USB Mass Storage Support Status

USB Mass Storage is implemented in USBSTOR driver and is fully working. Tested in WinXP + USBEHCI + USBSTOR. Mass storage support requires bulk and control transfers, which are implemented in USBEHCI.

HID Status

The HID framework is built on 5 drivers

  • HIDUSB – this is the interface driver for the USB bus. Currently supported devices are mice. Basic keyboard support should also work currently.
  • HIDCLASS – this is the class driver for HIDUSB and others. Functionality for mice & keyboard is implemented, though support for sending output reports is not implemented.
  • MOUHID – mouse function driver for USB hid standard – Fully implemented and working.
  • KBDHID – keyboard function driver for the hid standard – 90% implemented, needs KbdHid_InsertScanCodes implemented for keyboard scan code dispatching to kbdclass and led status indicator support (which requires sending output reports).
  • HIDPARSE – driver for parsing report descriptors – functionality implemented for mice, keyboard support needs HidParser_TranslateUsage fully implemented for modifier state (caps lock, num lock, scroll lock).

What already works

  • Mouse support has been tested in WinXP with ReactOS USBOHCI + HIDUSB + HIDCLASS + MOUHID + HIDPARSE and is working. The USB + HID stack also works in ReactOS.
  • Basic Keyboard support is nearly ready.
  • USB Mass storage support – Needs mountmgr / partmgr driver implemented. Will also need mountvol and other missing PnP stuff. - needs a few more issues to be resolved

See Also

References