DosUSB driver documentation

1. Introduction

DOS support for USB is currently very limited. There are only a
few drivers available, e.g. for mass storage devices.

DOS can work with a USB keyboard and a USB mouse only if the BIOS
features legacy support by doing a 8042 controller emulation for
these devices. With legacy support enabled, the BIOS will then also
support to boot from and to access a USB floppy drive or hard disk.

For Linux there are UHCI, OHCI and EHCI drivers available and a
lot of device drivers which are based on these USB controller
drivers. Using DOSUSB.COM it is now possible for DOS application
programs to communicate with all sorts of USB devices and to implement
USB device drivers for DOS.

DOSUSB.COM is a USB host controller driver for DOS. It is a TSR
program which implements a universal host controller driver (HCD) and a
universal serial bus driver (USBD). It can also be used with WIN 3.11.

DOSUSB.COM provides a software layer so application programs and
USB device drivers can be written supporting specific USB devices.

It builds frame lists for the USB host controllers, sets up
transfer descriptors and queue heads and schedules the transactions
requested by the USB device drivers.

2 Installation

Extract the zip file you have downloaded into a directory on your
hard disk e.g. c:\dosusb. This directory will then contain the
following files:

DOSUSB.COM      The driver
dosusb.htm      This file, the documentation for DOSUSB.COM
licence.txt     Licence information about DOSUSB.COM
usbview.exe     Application which displays the descriptors of
                a device
mouse.exe       USB mouse demo application
restart.exe     Enumerates all devices connected
address.exe     Displays all devices and their addresses
prnusb.sys      Device driver for printers using DosUSB
lpt1usb.sys     Device driver for printers replacing the LPT1: device
hplaser.exe     Prints the file dosusb.txt on a HP laserprinter
usbdisk.sys     Device driver for mass storage devices

The subdirectory SAMPLES will contain the source-code for the following samples:

usbview.bas     Source code for usbview.exe in Powerbasic
mouse.bas       Source code for mouse.exe in Powerbasic
keyboard.bas    Source code for reading a USB keyboard in Powerbasic
hplaser.bas     Source for an application to print the file dosusb.txt
                to an HP Laserjet printer
lq590.bas       Source for a sample to print to an Epson LQ-590 printer
setalt.bas      Source code to set alternate interface for a device
enum.c          Turbo C program to retrieve a device descriptor
enum.bas        Powerbasic sample to retrieve a device descriptor
enum.asm        Assembler sample to retrieve a device descriptor
address.bas     Source code for address.exe in Powerbasic
hplaser.pas     Pascal sample to print dosusb.txt to an HP Laserjet printer
hplaserv.bas    VBDOS sample to print dosusb.txt to an HP Laserjet printer
hplaserv.mak    VBDOS project file for hplaserv.bas
hplaserq.bas    Quickbasic sample to print dosusb.txt to an HP Laserjet printer
reset.bas       Powerbasic source for a reset command
reset.pas       Pascal source for reset command
restart.bas     Powerbasic source for restart.exe
restart.pas     Pascal source for restart command
icheck.bas      Powerbasic source for an installation check
cable.bas       Sample to send data via a PC connect USB cable
reader.bas      Sample to read sector zero of a memory card
stick.bas       Sample to read sector zero of a USB flash drive.
stick.pas       Sample in Pascal to read sector of a USB flash drive
floppy.bas      Sample to read sector zero of a floppy drive
camera.bas      Read isochronous traffic from a camera
scanner.bas     Sample which reads the identity of an Epson 1670 scanner
serial.bas      Sample terminal program using a USB/serial adapter
prnusb.asm      Source code for the printer device driver

To start DosUSB enter DOSUSB.COM at the DOS prompt. DosUSB
will then enumerate all the connected devices and install itself
as a resident program.

On laptops, the number of ports per controller may exceed the number of
USB sockets installed. DosUSB will then show more ports than can be used
with devices.

DosUSB itself requires about 23k of computer memory. However, it
also requests additional memory for each controller installed
in the computer.

DosUSB will work on a computer featuring UHCI or OHCI controllers.
It will try to determine whether OHCI or UHCI controllers are installed and
report this.

If the PC has an Intel or VIA mainboard it will have UHCI controllers.
These mainboards are used in most computers. If the PC has an EHCI controller
for USB 2.0, DosUSB will still be able to run, since the EHCI controller
works together with UHCI or OHCI controllers which DosUSB can use.

Since UHCI and OHCI just support up to 12Mbit/s, this is the upper limit
for ports supported by DosUSB. However, a 2.0 port with 480Mbit/s should also
work at 12Mbit/s.

3. USB Request Block

To request the execution of a transaction the device driver has
to use a USB Request Block (URB) of the following structure:

urbstruc struc
   transaction_type  byte  ;control (2Dh), in (69h), out (E1h) as hex code
   chain_end_flag    byte  ;reserved
   dev_add           byte
   end_point         byte
   error_code        byte  ;returned by dosuhci
   status            byte  ;returned by dosuhci
   transaction_flags word  ;reserved
   buffer_off        word  ;for in/out
   buffer_seg        word  ;for in/out
   buffer_length     word  ;for in/out
   actual_length     word  ;for in/out, (maximum length / bytes returned)
   setup_buffer_off  word  ;for control
   setup_buffer_seg  word  ;for control
   start_frame       word  ;reserved
   nr_of_packets     word  ;isochronous if set to one
   int_interval      byte  ;reserved
   error_count       byte  ;number of retries
   timeout           word  ;reserved
   next_urb_off      word  ;reserved
   next_urb_seg      word  ;reserved
urbstruc ends ;32 byte long

This URB structure is similar to the Linux URB.

Using this URB it is possible to schedule control, input and output
transactions. For control transactions, DosUSB can do the following
in and out transactions required to retrieve the requested data.

3.1 Elements of the URB structure


select the type of transaction scheduled, this can be either a
control, in or out transaction. For a control transaction enter
2D hex, for an in transaction enter 69 hex and for an out
transaction enter E1 hex.

You can also send commands to DosUHCI, if you enter FF hex as the
transaction code. The commands available are explained below.


this element is currently not used


enter the USB device address here of the device the scheduled
transaction shall be send to.

The device driver can either request the device descriptor for
all addresses from one to invalid to find the device in question.
Or you can use usbview to find the device manually.


each device has several endpoints. The device driver has to
select the right endpoint address for the control, in and out
transactions. There are different endpoints for bulk, interrupt,
control or isochronous transactions.


in this element DosUSB will return an error code, if it
encounters a problem with the scheduled transaction. The
following codes are currently defined:
1 - invalid device address,   2 - internal error,
3 - invalid transaction_type, 4 - invalid buffer length


this is the status byte returned by the USB controller after
executing the scheduled transaction. If a control transaction has
been scheduled, this element has the status byte of the last
transaction in the queue.
See details about this byte in the Intel UHCI design guide. In short:
Bit 0: Reserved, Bit 1: Bitstuff error, Bit 2: CRC/Timeout, Bit 3: NAK,
Bit 4: Babble detected, Bit 5: Data Buffer error, Bit 6: Stalled,
Bit 7: Active
So e.g. 88 hex means a NAK received, since the active bit is set the data
packet can be retried, 44 hex means a CRC/Timeout error which caused a stall.
The device may need a reset.
The OHCI controller returns different completion codes than the UHCI
controller. To simplify driver development, the DOSUSB driver translates the
OHCI completion codes to UHCI status codes. However, in the dosusb.log file
the OHCI codes are specified.
OHCI completion code 1 is translated to 44h, 2 to 42h, 3 to 44h, 4 to 40h,
5,6 and 7 to 44h, 8 to 50h, 9 to 00h, 12 to 20h, 13 to A0h and 14 to 88h.


this element is currently not used

buffer_off / buffer_seg

enter a pointer to a buffer here, where either the data to be
send by an out transaction or the data to be returned by an in or
control transaction shall be placed


specify either the length of the out buffer or the expected
length of the data to be returned by an in or control transaction
If you set buffer_length greater than actual_length
(maximum length) DosUSB will schedule the number of in
transactions required to retrieve the amount of data specified in
buffer_length. DosUSB accepts a buffer_length up to 1024 bytes.
In the current version I recommend to specify up to the actual_length.


to schedule a transaction, enter the maximum length supported by
the addressed endpoint here. After the transaction is completed
this element will have the number of bytes returned.

This number is given as returned by the UHCI controller, so 7FFh
means zero bytes, 0 means one byte, 1 means two bytes and so on.
The maximum length, however, needs to be entered as 8 for 8
bytes, which will be returned as the number 7.

For an OHCI controller, the number is the real length in bytes.

setup_buffer_off / setup_buffer_seg  

for control transactions, enter a pointer to the request here.
This can e.g. be a device descriptor request


if this element has a value greater zero, DosUSB will schedule a
transaction for isochronous traffic.
Isochronous support is not yet implemented for OHCI!


this instructs the UHCI controller to retry unsuccessful transactions.
Valid values are: 0 - default (3 retries), 1 - 1 retry, 2 - 2 retries,
3 - 3 retries. For OHCI this is set to three and cannot be modified.
DosUSB will not have the host controller retry if a NAK is received.
These transactions are terminated with 88h in the status element and have
to be retried by the application.

All other elements are currently unused. They are provided so a
device driver that is written for the current version of DosUSB
will run without changes with future versions too.

3.2. Scheduling control transactions

In the case of a control transaction DosUSB will return the
input in the buffer pointed to buffer_seg and buffer_off, if buffer_seg
and buffer_off are not zero and buffer_length is greater than zero.

For a control transaction such as a device descriptor request
DosUSB will return the device descriptor in buffer and
acknowledge the receipt to the device with a zero out
transaction. In this case the actual_length field has to be equal
to the maximum packet length and buffer_length has to specify the
requested length of the descriptor which shall be returned.

If buffer_length is set to zero, DosUSB will do an in
transaction but no out transaction. So for a set configuration
transaction you have to set buffer_length to zero since this
transaction does not return data from the device and therefore
requires no out transaction.

If you set buffer_seg and buffer_off to zero, DosUSB will just
do an control transaction. The driver calling DosUSB can then
request the in and out transactions required following the control

3.3. Calling DosUSB to execute the URB

To have DosUSB execute the transaction defined by the URB, you
have to place a pointer to the URB in the DS:DX registers and
call interrupt 65h.
The DS register has to contain the segment part of the pointer
and the DX register the offset part of it.

With the /I commandline parameter you can specify a different
interrupt to be used by DosUSB. For example /I64 will ask
DosUSB to use interrupt 64h. Use the range 60h-67h.

Using the URB you can only schedule a transaction to a single
device specified by the device address. So you can send and
receive data from a mass storage device or send data to a
printer. If you have a camera, which sends a constant stream of
data or a mouse, DosUSB will not be able to retrieve that data
while it is executing a transaction to e.g. a printer.

4. Commands to DosUSB

If you enter FFh as the transaction type, you can specify in the
ax register the following commands:

ax=1: If dev_add is zero, DosUSB will reset all devices and enumerate
      them again. It will not enumerate new devices and thus all devices
      keep their address. If dev_add is greater than zero, DosUSB will
      just reset and enumerate the device with that address. It will not
      output anything to screen in that case. Instead, if the enumeration
      was successful DosUSB will return a 0 or 30h, if it failed, it will
      return a 1 or 31h in the transaction_type field of the urb.
ax=2: enables debug output                                
ax=3: disables debug output
ax=4: displays the URB received from a device driver. You also have to
      specify a valid device address in the URB here.
ax=5: set data toggle to zero, e.g. after a clear_feature(endpoint_halt)
      command. You also have to specify the device address and endpoint
      in the URB here.
ax=6: allows to check if DosUSB is installed. Will return "G" or 47h in
      the transaction type field of the URB. See the icheck.bas sample.
      Check if the interrupt is initialized first before using this.
ax=7: allows to check whether a UHCI or OHCI controller is installed.
      Will return in the transaction type field of the URB a "U" or 55h
      if UHCI and an "O" or 4Fh if OHCI has been determined by DosUSB.
ax=8: DosUSB will check all ports for devices connected and reset and
      enumerate all devices it finds. If there are any additional devices
      or devices have been removed, all devices may receive a new address.
      The device on port zero of the first controller will get address number
      one and so forth. If this device has not changed, it will keep its
      address. However, if there has been no device on that port before, all
      devices will get a new address.
ax=9: allows to determine the type of USB controller installed. Will return
      the PCI vendor ID in the field next_urb_off of the URB and the PCI
      device ID in the field next_urb_seg.

5. Commandline options

DosUSB currently supports the following command line options:
/D write debug output to dosusb.log file
/I change interrupt to call DosUSB URB
/X exclude controller

The /X option allows to exclude a USB controller, which will not be used by
DosUSB. E.g. /XEC00 will exclude the controller at I/O address EC00 hex.
If you want a USB mouse or keyboard to be controlled by the BIOS while using
DosUSB to communicate with another device at a different controller, you
can use this command to exclude the controller where the mouse and keyboard
are connected.

6. Debug mode

DosUSB offers a trace of the transactions performed via the UHCI
or OHCI interface. This allows to monitor whether the scheduled
transactions where successful.

If DosUSB is called with the /D command line, the debug output
is written into the dosusb.log file while DosUSB is running.

Using the transaction descriptor FF hex and the command 02 you
can turn on the trace any time and using the command 03 you can
turn it off again. In this case, the debug output is written to
the screen.
After each transaction the trace stops and asks for a keypress.
If you enter "c" here, the screen will be cleared.

For each UHCI transaction the trace contains the following lines:

a) the bytes which make up the transaction descriptor as it is
returned by the UHCI interface. There are two differences of this
transaction descriptor to the one written to the UHCI interface:
the status byte has been updated by the controller and DosUHCI
puts the value 500h into the actual length field to check if it
has been updated by the controller. Following the transaction
descriptor the transaction type is given (IN, OUT or CTRL), the
bits set (LS=low speed, SPD=short packet detect, IOS=isochronous
traffic , IOC=interupt on complete) and the error limit
specified, usually three errors.

Above the transaction descriptor there are numbers which shall
allow to locate the bytes in the descriptor or AL for actual
length, ST for status, PI for PID and AD for device address.

b) Then the result of the transaction(s) is displayed.
Following this there are specified: the device address, the
endpoint, the data toggle bit and the maximum packet length.

If buffer_length is greater than actual_length (maximum length),
there will be buffer_length divided by actual_length number of
transactions. These will be displayed beneath each other here.

c) The final line shows the bytes in hexadecimal of the data sent
or returned by this transaction.

For control transactions, the request is also displayed at the
beginning of the transaction.

For OHCI transactions the trace is set up differently.

For control transactions, the request is also displayed at the
beginning of the transaction.

An OHCI transaction is set up by an endpoint descriptor (ED:) and an
transaction descriptor (TD:). The trace will list both after the transaction.

It will also show the TC field of the endpoint descriptor, the value in
the toggle field of the transaction descriptor and the completion code in
numeric and text form followed by the number of bytes transfered.

7. Planned features for the next release

- support for isochronous transfers in OHCI.

8. USB reference material

Writing USB device drivers requires a good understanding of the
USB specifications. Here are some documents to get started:

"USB in a nutshell"
A good introduction to the USB specifications. Available from:

"USB Made Simple"
Another fine introduction by MQP Electronics.

Some notes about the USB specifications can be found here:

"Universal Host Controller Interface (UHCI) Design Guide" by Intel.
This is the interface DosUSB is based on for its UHCI part.

"OpenHCI Open Host Controller Interface Specification for USB" by Compay, Microsoft,
National Semiconductor. This is the specification for the OHCI part of DosUSB.

"USB 2.0 specifications"
Once you've read "USB in a nutshell" you have to consult this reference.

"USB complete" by Jan Axelson
Probably the most important book on USB. The author's web site is:

"USB Tracker" by Ellisys
This is a good USB scope and currently one with a relatively low
price. If you download their demonstration software, you get
excellent examples of USB communications with different devices.

To write a device driver for a floppy drive or mass storage
device you will usually only need the class specifications from However, many devices have vendor specific commands
which often are not made available. Some of these specifications
can be gathered from the Linux USB driver implementations.

9. USB analysers

If you develop a device driver using DosUSB, a USB protocol
analyser will be of great value.

The best choice is a hardware monitor such as the USB Tracker by

Besides this device, there are software USB analysers e.g.:
USB Monitor at,
USBinfo at
or SourceUSB at

There is also a free software USB sniffer at
or at

These tools are cheaper than the USB Tracker but only allow you
to monitor the traffic between Windows and a USB device. However,
you can see how windows communicates with the device.

Finally there are devices which allow you to use a logic analyser
to monitor USB traffic:

10. Samples

The package contains samples of programs which use the DosUSB
driver. These are not complete device drivers, they shall only
show the functionality of the DosUSB driver.

USBVIEW is a Powerbasic program which will display all
descriptors of a device.

ADDRESS is a utility in Powerbasic which displays all connected devices
and their device addresses.

MOUSE is a demo program which reads the input from a USB mouse.

LQ590.bas is a sample which prints a short text on an Epson LQ-590

HPLASER.bas will print the file DOSUSB.TXT on a HP Laserprinter.
It uses PCL commands to set up the printer for text output.

Most low cost USB printers are GDI or Windows printers which will not
print ASCII codes sent to them. They expect data which controls their
print head. This protocol is vendor specific and usually not available.
If a printer accepts ASCII code via its parallel interface, it usually
can also do this via its USB interface. GDI printers can only be used with
Win 3.11 since there are no GDI drivers for DOS available.

SETALT.bas is a sample to set an alternate interface of a device.

ENUM.c is a Turbo C sample to retrieve a device descriptor.

ENUM.bas is a Powerbasic sample to retrieve a device descriptor.

ENUM.asm retrieves a device descriptor using assembler.

HPLASER.pas is a sample in Pascal to print dosusb.txt to an HP Laserjet
Michel LECLERC translated HPLASER.bas to this Pascal sample.

HPLASERV.bas is a Visual Basic for DOS sample to print dosusb.txt to an
HP Laserjet printer. Converted from hplaser.bas for Powerbasic.

RESET.bas resets and enumerates all connected devices. This will not check
for additionally connected devices and not remove the addresses
for disconnected devices. So the addresses for all devices will not change.

RESTART.bas resets and enumerates all connected devices. This will assign
addresses to additionally connected devices and remove the addresses
for disconnected devices. The addresses for other devices may change.

ICHECK.bas checks whether the DosUSB driver is installed and running.

KEYBOARD.bas reads the keys typed on a USB keyboard. The USB HID to PS/2
scan code translation table can be found at the microsoft site in the document:

CABLE.bas is a sample which sends data via a PC connect USB cable from one
USB port to a second USB port.

READER.bas reads sector zero of a memory card in a USB card reader.

STICK.BAS is very similar to READER.bas and reads sector zero of a
USB memory stick.

STICK.PAS, RESTART.PAS and RESET.PAS are samples converted to
Pascal by Joe da Silva

FLOPPY.bas will read the boot sector of a floppy in a USB floppy drive.

CAMERA.bas reads isochronous data from a Trust 120 Spacecam camera and
saves it in the file image.yuv. Will run with UHCI only.

SCANNER.bas is a sample which reads the identity of an Epson Perfection
1670 scanner. This does not use the ESC/I commands.

PRNUSB.sys is a printer device driver which uses DosUSB to print to USB
printers. Tested with a HP 2420d Laserprinter and will also run with a
HP 880C, a HP 5940 and a HP 460C inkjet printer. It will also work with
parallel to USB adapters. Check the endpoints and use the setalt utility to
set the interface before printing here.

It is loaded with a "device=" statement in the config.sys file. Load
DosUSB then, do not use the /D command line option here!
The default device address is one, the default device endpoint is two. Use
the command line options e.g. /D2 /E1 to select device address two and
endpoint number one. Use USBView to determine the right settings for your
Cannot be used with low cost GDI printers, since these do not accept ASCII
code for printing. However, since drivers for GDI printers are available for WIN 3.11,
if you use DosUSB and PRNUSB.SYS with WIN 3.11, you can also use these GDI printers with PRNUSB.SYS.There are no drivers for these printers in DOS, however.

Use "type dosusb.txt > prnusb" to print this file from the DOS prompt. Or
open "prnusb" as a file in your application program.
PRNUSB.asm is the source code for this driver.

LPT1USB.SYS is a variant of PRNUSB.SYS which installs as a LPT1: device. So
you can print from the DOS Editor or other application programs directly.

USBDISK.SYS is a device driver for flash drives and other mass storage devices
such as USB hard disks and PCMCIA cards in USB card readers.
It is currently provided as a beta version.

Since DosUSB does not support EHCI which allows for higher transfer speeds,
the transfer is a bit slower than the one achived with Windows.

It is loaded with a "device=" statement in the config.sys file such as:
device=c:\dosusb\usbdisk.sys provided the file usbdisk.sys in the c:\dosusb
directory on your hard disk.

If you have more than one USB device connected to the PC and the flash drive
is not the first device to get address number one, you can use the /D command
line option. This way you can specify the address of the flash drive. DosUSB
will always give the same address to each device connected to the PC as long
as no device is removed or added. So if you found out, which address the
flash drive gets from DosUSB you can specify that with the /D option. Without
the /D option USBDISK.SYS assumes address one.
USBDISK.SYS reads the device descriptor to determine the endpoints so these do
not need to be set by a command line option.

Then boot the PC to have DOS load usbdisk.sys as specified in config.sys.

When DOS boots and loads the USBDISK.SYS driver, the driver will display the drive
letter DOS has assigned to the mass storage device.

Plug in your flash drive now. Always use the same slot, to avoid to get a
different address than before.

Start dosusb (without the /D option for log-file creation)

Now you can do a "dir" command on the flash drive and copy files from the drive
to the hard disk and from the disk to the drive. You can also delete files etc.
Even if there are no files in the directory, DOS does a lot of reads which
will cause a long delay at the end of the "dir" command to determine the free space
on the device. Using "dir" with the "/B" option will be much quicker.

If you want to boot the PC from a floppy disk or CD, DOS will often not assign a drive
letter which is correct when usbdisk.sys is loaded using the config.sys file. In this case
you should not put usbdisk.sys into the config.sys file but use the utility to
load usbdisk.sys later after loading DOSUSB.COM.


USBDISK.SYS does not support changing the mass storage device yet. If you connect a different flash disk you have to reboot your PC to reload USBDISK.SYS or your data will be corrupted.

If the mass storage device is not formatted it is not supported by USBDISK.SYS. It will not return that the device is unformatted.

USBDISK.SYS will just access the first partition of a USB hard disk.

If your flash disk has a write protect switch, this will not be queried by USBDISK.SYS. So DOS can copy to the flash disk even when the write protect switch is set.

Windows opens a small window showing how much data has been copied. DOS does
not do that. So with large files it seems that nothing is happening - but
DOS does copy!

Better remove usbdisk from the config.sys file before booting Windows - some Windows
versions may try to access the device which USBDISK.SYS provides when running SCANDISK.

So there are several issues left to improve for the next release. However, it took quite a lot of time to develop USBDISK.SYS and it can be used to transfer files successfully now.

17th February 2007 Georg Potthast