Functional USB data exchange is used to move data to and from the device. There are three types of USB data transfers: Bulk, Interrupt and Isochronous , which are described in detail in sections 3.6.2 – 3.6.4 of the manual.
Functional USB data transfers can be implemented using two alternative methods: single blocking transfers and streaming transfers, both supported by WinDriver, as explained in the following sections. The generated DriverWizard USB code [5.2.3] and the generic WinDriver/util/usb_diag.exe utility [1.9.2] (source code located under the WinDriver/samples/usb_diag directory) enable the user to select which type of transfer to perform.
In the single blocking USB data transfer scheme, blocks of data are synchronously transferred (hence – "blocking") between the host and the device, per request from the host (hence – "single" transfers).
WinDriver's WDU_Transfer function, and the
WDU_TransferBulk, WDU_TransferIsoch, and
WDU_TransferInterrupt convenience functions – all
described in section B.4.8 of the
manual – enable you to easily impelment single blocking USB data
transfers.
You can also perform single blocking transfers using the DriverWizard utility
(which uses the WDU_Transfer function), as demonstrated in
section 5.2 of the manual.
In the streaming USB data transfer scheme, data is continuously streamed between the host and the device, using internal buffers allocated by the host driver – "streams".
Stream transfers allow for a sequential data flow between the host and the device, and can be used to reduce single blocking transfer overhead, which may occur as a result of multiple function calls and context switches between user and kernel modes. This is especially relevant for devices with small data buffers, which might, for example, overwrite data before the host is able to read it, due to a gap in the data flow between the host and device.
WinDriver's WDU_StreamXXX functions, described in section
B.4.9 of the manual, enable you to
impelment USB streaming data transfers. Note: These functions are currently
supported on Windows and Windows CE.
To begin performing stream transfers, call the WDU_StreamOpen
function [B.4.9.1]. When this function is called,
WinDriver creates a new stream object for the specified data pipe. You can open a
stream for any pipe except for the control pipe (Pipe 0). The stream's data
transfer direction – read/write – is derived from the direction of
its pipe.
WinDriver supports both blocking and non-blocking stream transfers. The open
function's fBlocking parameter indicates which type of transfer to
perform (see explanation below). Streams that perform blocking transfers will
henceforth be referred to as "blocking streams", and streams that perform
non-blocking transfers will be referred to as "non-blocking streams".
The function's dwRxTxTimeout parameter indicates the desired
timeout period for transfers between the stream and the device.
After opening a stream, call WDU_StreamStart [B.4.9.2] to begin data transfers between the stream's
data buffer and the device.
In the case of a read stream, the driver will constantly read data from the
device into the stream's buffer, in blocks of a pre-defined size (as set in the
dwRxSize parameter of the WDU_StreamOpen function
[B.4.9.1]. In the case of a write stream, the driver
will constantly check for data in the stream's data buffer and write any data
that is found to the device.
To read data from a read stream to the user-mode host application, call
WDU_StreamRead [B.4.9.3].
In case of a blocking stream, the read function blocks until the entire amount
of data requested by the application is transferred from the stream to the
application, or until the stream's attempt to read data from the device times
out.
In the case of a non-blocking stream, the function transfers to the application
as much of the requested data as possible, subject to the amount of data
currently available in the stream's data buffer, and returns immediately.
To write data from the user-mode host application to a write the stream, call
WDU_StreamWrite [B.4.9.4].
In case of a blocking stream, the function blocks until the entire data is
written to the stream, or until the stream's attempt to write data to the
device times out.
In the case of a non-blocking stream, the function writes as much of the write
data as currently possible to the stream, and returns immediately.
For both blocking and non-blocking transfers, the read/write function returns
the amount of bytes actually transferred between the stream and the calling
application within an output parameter – *pdwBytesRead
[B.4.9.3] / *pdwBytesWritten [B.4.9.4].
You can flush an active stream at any time by calling the
WDU_StreamFlush function [B.4.9.5],
which writes the entire contents of the stream's data buffer to the device (for
a write stream), and blocks until all pending I/O for the stream is
handled.
You can flush both blocking and non-blocking streams.
You can call WDU_StreamGetStatus [B.4.9.6] for any open stream in order to get the
stream's current status information.
To stop the data streaming between an active stream and the device, call
WDU_StreamStop [B.4.9.7]. In the case
of a write stream, the function flushes the stream – i.e. writes its
contents to the device – before stopping it.
An open stream can be stopped and restarted at any time until it is closed.
To close an open stream, call WDU_StreamClose
[B.4.9.8].
The function stops the stream, including flushing its data to the device (in
the case of a write stream), before closing it.
Note: Each call to WDU_StreamOpen must have a matching call to
WDU_StreamClose later on in the code in order to perform the
necessary cleanup.