Wdusb Manual
Wdusb Manual
Manual
Jungo Connectivity Ltd.
Version 12.5.1
WinDriver™ USB User's Manual
Copyright © 2017 Jungo Connectivity Ltd. All Rights Reserved
Information in this document is subject to change without notice. The software described in this document is furnished under a license
agreement. The software may be used, copied or distributed only in accordance with that agreement. No part of this publication
may be reproduced, stored in a retrieval system, or transmitted in any form or any means, electronically or mechanically, including
photocopying and recording for any purpose without the written permission of Jungo Connectivity Ltd.
Brand and product names mentioned in this document are trademarks of their respective owners and are used here only for
identification purposes.
Don't let the size of this manual fool you. WinDriver makes developing device drivers an
easy task that takes hours instead of months. Most of this manual deals with the features that
WinDriver offers to the advanced user. However, most developers will find that reading this
chapter and glancing through the DriverWizard and function-reference chapters is all they need to
successfully write their driver.
Visit Jungo's web site at http://www.jungo.com for the latest news about WinDriver and other
driver development tools that Jungo offers.
1.2. Background
• Learn new tools for developing/debugging in kernel mode (WDK, ETK, DDI/DKI).
• Write the kernel-mode device driver that does the basic hardware input/output.
• Write the application in user mode that accesses the hardware through the device driver written
in kernel mode.
• Repeat the first four steps for each new operating system on which the code should run.
• Cross Platform — The driver created with WinDriver will run on Windows 10/8.1/Server
2012 R2/8/Server 2012/7/Server 2008 R2/Server 2008, Embedded Windows 8.1/8/7, Windows
CE (a.k.a. Windows Embedded Compact) 4.x–8.x (including Windows Mobile), and Linux. In
other words — write it once, run it on many platforms.
• Friendly Wizards — DriverWizard (included) is a graphical diagnostics tool that lets you
view the device's resources and test the communication with the hardware with just a few
mouse clicks, before writing a single line of code. Once the device is operating to your
satisfaction, DriverWizard creates the skeletal driver source code, giving access-functions to all
the resources on the hardware.
1.3. Conclusion
Using WinDriver, a developer need only do the following to create an application that accesses
the custom hardware:
• Automatically generate the device-driver code from within DriverWizard, or use one of the
WinDriver samples as the basis for the application.
Your hardware-access application will run on all the supported platforms [1.6] — just recompile
the code for the target platform. The code is binary-compatible across Windows 10/8.1/Server
2012 R2/8/Server 2012/7/Server 2008 R2/Server 2008 platforms; there is no need to rebuild the
code when porting it across binary-compatible platforms.
• Friendly DriverWizard allows hardware diagnostics without writing a single line of code.
• Automatically generates the driver code for the project in C, Visual Basic .NET, or C#.
• Applications are binary compatible across Windows 10/8.1/Server 2012 R2/8/Server 2012/7/
Server 2008 R2/Server 2008.
• Applications are source code compatible across all supported operating systems — Windows
10/8.1/Server 2012 R2/8/Server 2012/7/Server 2008 R2/Server 2008, Embedded Windows
8.1/8/7, Windows CE (a.k.a. Windows Embedded Compact) 4.x–8.x (including Windows
Mobile), and Linux.
• WinDriver Windows drivers are compliant with Microsoft's Windows Certification Program
For hardware access, your application calls one of the WinDriver user-mode functions. The user-
mode function calls the WinDriver kernel, which accesses the hardware for you through the
native calls of the operating system.
• Windows 10/8.1/Server 2012 R2/8/Server 2012/7/Server 2008 R2/Server 2008 and Embedded
Windows 8.1/8/7 — henceforth collectively: Windows
• Linux
The same source code will run on all supported platforms — simply recompile it for the target
platform. The source code is binary compatible across Windows 10/8.1/Server 2012 R2/8/Server
2012/7/Server 2008 R2/Server 2008; WinDriver executables can be ported among the binary-
compatible platforms without recompilation.
Even if your code is meant only for one of the supported operating systems, using WinDriver
will give you the flexibility to move your driver to another operating system in the future without
needing to change your code.
OS-specific support is provided only for operating systems with official vendor support.
• When using DriverWizard, a dialogue box with a message stating that an evaluation version is
being run appears on every interaction with the hardware.
• In the Linux and Windows CE versions, the driver will remain operational for 60 minutes, after
which time it must be restarted.
• The Windows evaluation version expires 30 days from the date of installation.
2. Let DriverWizard generate skeletal code for your driver, or use one of the WinDriver samples
as the basis for your driver application.
The code generated by DriverWizard is a diagnostics program that contains functions that
perform data transfers on the device's pipes, send requests to the control pipe, change the
active alternate setting, reset pipes, and more.
1.8.2. On Windows CE
1. Plug your hardware into a Windows host machine.
4. Modify this code, using MS eMbedded Visual C++, to meet your specific needs. If you
are using MS Platform Builder, activate it and insert the generated *.pbp into your project
solution.
• WinDriver modules
• Utilities
• Samples
wdu_lib.h: Declarations and definitions of the WinDriver USB (WDU) library, which
provides convenient wrapper USB APIs.
• Debug Monitor — a debugging tool that collects information about your driver as it runs. This
tool is available both as a fully graphical application — WinDriver/util/wddebug_gui — and
as a console-mode application — WinDriver/util/wddebug. The console-mode version also
supports GUI execution on Windows CE platforms that don't have a command-line prompt.
For details regarding the Debug Monitor, refer to Section 7.2.
• WinDriver distribution package (WinDriver/redist) — the files you include in the driver
distribution to customers.
• This manual — the full WinDriver manual (this document), in different formats, can be found
under the WinDriver/docs directory.
1.9.2. Utilities
• usb_diag.exe (WinDriver/util/usb_diag.exe) — enables the user to view the resources of
connected USB devices and communicate with the devices — transfer data to/from the device,
set the active alternate setting, reset pipes, etc.
On Windows the program identifies all devices that have been registered to work with
WinDriver using an INF file. On the other supported operating systems the program identifies
all USB devices connected to the target platform.
1.9.3. Samples
WinDriver includes a variety of samples that demonstrate how to use WinDriver's API to
communicate with your device and perform various driver tasks.
• .NET C# and Visual Basic .NET samples (Windows): found under the WinDriver\csharp.net
and WinDriver\vb.net directories (respectively).
Using WinDriver, you do not need to familiarize yourself with the internal workings of
driver development. As explained in Chapter 1 of the manual, WinDriver enables you to
communicate with your hardware and develop a driver for your device from the user mode,
using only WinDriver's simple APIs, without any need for driver or kernel development
knowledge.
A driver acts like a translator between the device and programs that use the device. Each device
has its own set of specialized commands that only its driver knows. In contrast, most programs
access devices by using generic commands. The driver, therefore, accepts generic commands
from a program and then translates them into specialized commands for the device.
Monolithic drivers are supported in all operating systems including all Windows platforms and all
Unix platforms.
Layered drivers are sometimes also known as filter drivers, and are supported in all operating
systems including all Windows platforms and all Unix platforms.
Miniport drivers are also called miniclass drivers or minidrivers, and are supported in the
Windows 7 and higher operating systems.
The Windows 7 and higher operating systems provide several driver classes (called ports)
that handle the common functionality of their class. It is then up to the user to add only the
functionality that has to do with the inner workings of the specific hardware. The NDIS miniport
driver is one example of such a driver. The NDIS miniport framework is used to create network
drivers that hook up to Windows's communication stacks, and are therefore accessible to common
communication calls used by applications. The Windows kernel provides drivers for the various
communication stacks and other code that is common to communication cards. Due to the NDIS
framework, the network card developer does not have to write all of this code, only the code that
is specific to the network card he is developing.
Unix device drivers are either layered or monolithic drivers. A monolithic driver can be perceived
as a one-layer layered driver.
Under Linux, a block device can be accessed like a character device, as in Unix, but also has a
block-oriented interface that is invisible to the user or application.
Traditionally, under Unix, device drivers are linked with the kernel, and the system is brought
down and restarted after installing a new driver. Linux introduces the concept of a dynamically
loadable driver called a module. Linux modules can be loaded or removed dynamically without
requiring the system to be shut down. A Linux driver can be written so that it is statically linked
or written in a modular form that allows it to be dynamically loaded. This makes Linux memory
usage very efficient because modules can be written to probe for their own hardware and unload
themselves if they cannot find the hardware they are looking for.
Like Unix device drivers, Linux device drivers are either layered or monolithic drivers.
There is some global initialization that every driver needs to perform only once when
it is loaded for the first time. This global initialization is the responsibility of the
DriverEntry()/init_module() routine. The entry function also registers which driver
callbacks will be called by the operating system. These driver callbacks are operating system
requests for services from the driver. In Windows, these callbacks are called dispatch routines,
and in Linux they are called file operations. Each registered callback is called by the operating
system as a result of some criteria, such as disconnection of hardware, for example.
In Windows, the hardware-driver association is performed via an INF file, which registers the
device to work with the driver. This association is performed before the DriverEntry() routine
is called. The operating system recognizes the device, checks its database to identify which INF
file is associated with the device, and according to the INF file, calls the driver's entry point.
In Linux, the hardware-driver association is defined in the driver's init_module() routine. This
routine includes a callback that indicates which hardware the driver is designated to handle. The
operating system calls the driver's entry point, based on the definition in the code.
On Windows, Windows CE, and Linux, the application can use the OS file-access API to open
a handle to the driver (e.g., using the Windows CreateFile() function or using the Linux
open() function), and then read and write from/to the device by passing the handle to the relevant
OS file-access functions (e.g., the Windows ReadFile() and WriteFile() functions, or the
Linux read() and write() functions).
The application sends requests to the driver via I/O control (IOCTL) calls, using the custom OS
APIs provided for this purpose (e.g., the Windows DeviceIoControl() function, or the Linux
ioctl() function).
The data passed between the driver and the application via the IOCTL calls is encapsulated using
custom OS mechanisms. For example, on Windows the data is passed via an I/O Request Packet
(IRP) structure, and is encapsulated by the I/O Manager.
The references to the WinDriver USB toolkit in this chapter relate to the standard
WinDriver USB toolkit for development of USB host drivers.
The USB specification allows for the connection of a maximum of 127 peripheral devices
(including hubs) to the system, either on the same port or on different ports.
USB also supports Plug-and-Play installation and hot swapping. The USB 1.1 standard supports
both isochronous and asynchronous data transfers and has dual speed data transfer: 1.5 Mb/s
(megabits per second) for low-speed USB devices and 12 Mb/s for full-speed USB devices
(much faster than the original serial port). Cables connecting the device to the PC can be up to
five meters (16.4 feet) long. USB includes built-in power distribution for low power devices and
can provide limited power (up to 500 mA of current) to devices attached on the bus.
The USB 2.0 standard supports a signalling rate of 480 Mb/s, known as 'high-speed', which is 40
times faster than the USB 1.1 full-speed transfer rate.
USB 2.0 is fully forward- and backward-compatible with USB 1.1 and uses existing cables and
connectors.
USB 2.0 supports connections with PC peripherals that provide expanded functionality and
require wider bandwidth. In addition, it can handle a larger number of peripherals simultaneously.
USB 2.0 enhances the user's experience of many applications, including interactive gaming,
broadband Internet access, desktop and Web publishing, Internet services and conferencing.
Because of its benefits (described also in Section 3.2 below), USB is currently enjoying broad
market acceptance.
• Suitable for device bandwidths ranging from a few Kb/s to hundreds of Mb/s
• Supports isochronous as well as asynchronous transfer types over the same set of wires
• Supports a data transfer rate of up to 480 Mb/s (high-speed) for USB 2.0 (for the operating
systems that officially support this standard) and up to 12 Mb/s (full-speed) for USB 1.1
• Guaranteed bandwidth and low latencies; appropriate for telephony, audio, etc. (isochronous
transfer may use almost the entire bus bandwidth)
• Flexibility: supports a wide range of packet sizes and a wide range of data transfer rates
• Robustness: built-in error handling mechanism and dynamic insertion and removal of devices
with no delay observed by the user
• USB Host: The USB host platform is where the USB host controller is installed and where the
client software/device driver runs. The USB Host Controller is the interface between the host
and the USB peripherals. The host is responsible for detecting the insertion and removal of
USB devices, managing the control and data flow between the host and the devices, providing
power to attached devices and more.
• USB Hub: A USB device that allows multiple USB devices to attach to a single USB port on
a USB host. Hubs on the back plane of the hosts are called root hubs. Other hubs are called
external hubs.
• USB Function: A USB device that can transmit or receive data or control information over the
bus and that provides a function. A function is typically implemented as a separate peripheral
device that plugs into a port on a hub using a cable. However, it is also possible to create a
compound device, which is a physical package that implements multiple functions and an
embedded hub with a single USB cable. A compound device appears to the host as a hub with
one or more non-removable USB devices, which may have ports to support the connection of
external devices.
Data can be transferred between the host and only one device at a time (peer to peer
communication). However, two hosts cannot communicate directly, nor can two USB devices
(with the exception of On-The-Go (OTG) devices, where one device acts as the master (host) and
the other as the slave.)
The data on the USB bus is transferred via pipes that run between software memory buffers on the
host and endpoints on the device.
Data flow on the USB bus is half-duplex, i.e., data can be transmitted only in one direction at a
given time.
An endpoint is a uniquely identifiable entity on a USB device, which is the source or terminus of
the data that flows from or to the device. Each USB device, logical or physical, has a collection of
independent endpoints. The three USB speeds (low, full and high) all support one bi-directional
control endpoint (endpoint zero) and 15 unidirectional endpoints. Each unidirectional endpoint
can be used for either inbound or outbound transfers, so theoretically there are 30 supported
endpoints.
Each endpoint has the following attributes: bus access frequency, bandwidth requirement,
endpoint number, error handling mechanism, maximum packet size that can be transmitted or
received, transfer type and direction (into or out of the device).
A pipe is a logical component that represents an association between an endpoint on the USB
device and software on the host. Data is moved to and from a device through a pipe. A pipe can
be either a stream pipe or a message pipe, depending on the type of data transfer used in the pipe.
Stream pipes handle interrupt, bulk and isochronous transfers, while message pipes support the
control transfer type. The different USB transfer types are discussed below [3.6].
• Functional Data Exchange is used to move data to and from the device. There are three types
of USB data transfers: Bulk, Interrupt and Isochronous .
Control exchange takes place via a control pipe — the default pipe 0, which always exists. The
control transfer consists of a setup stage (in which a setup packet is sent from the host to the
device), an optional data stage and a status stage.
Figure 3.2 below depicts a USB device with one bi-directional control pipe (endpoint) and two
functional data transfer pipes (endpoints), as identified by WinDriver's DriverWizard utility
(discussed in Chapter 5).
Figure 3.2. USB Pipes
More information on how to implement the control transfer by sending setup packets can be
found in Section 8.2.
The USB specification provides for the following data transfer types:
This transfer type is used for low-, full- and high-speed devices.
Each USB device has at least one control pipe (default pipe), which provides access to the
configuration, status and control information.
The control pipe is bi-directional — i.e., data can flow in both directions.
Control transfer has a robust error detection, recovery and retransmission mechanism and retries
are made without the involvement of the driver.
The maximum packet size for control endpoints can be only 8 bytes for low-speed devices; 8, 16,
32, or 64 bytes for full-speed devices; and only 64 bytes for high-speed devices.
For more in-depth information regarding USB control transfers and their implementation, refer to
Section 8.2 of the manual.
This transfer type can be used by full-speed and high-speed devices, but not by low-speed
devices.
The isochronous pipe is unidirectional, i.e., a certain endpoint can either transmit or receive
information. Bi-directional isochronous communication requires two isochronous pipes, one in
each direction.
USB guarantees the isochronous transfer access to the USB bandwidth (i.e., it reserves the
required amount of bytes of the USB frame) with bounded latency, and guarantees the data
transfer rate through the pipe, unless there is less data transmitted.
Since timeliness is more important than correctness in this type of transfer, no retries are made in
case of error in the data transfer. However, the data receiver can determine that an error occurred
on the bus.
This transfer type can be used for low-, full- and high-speed devices.
Interrupt transfer type guarantees a maximum service period and that delivery will be re-
attempted in the next period if there is an error on the bus.
The interrupt pipe, like the isochronous pipe, is unidirectional and periodical.
The maximum packet size for interrupt endpoints can be 8 bytes or less for low-speed devices; 64
bytes or less for full-speed devices; and 1,024 bytes or less for high-speed devices.
This transfer type can be used by full-speed and high-speed devices, but not by low-speed
devices.
Bulk transfer allows access to the bus on an "as-available" basis, guarantees the data transfer but
not the latency, and provides an error check mechanism with retries attempts. If part of the USB
bandwidth is not being used for other transfers, the system will use it for bulk transfer.
Like the other stream pipes (isochronous and interrupt), the bulk pipe is also unidirectional, so bi-
directional transfers require two endpoints.
The maximum packet size for bulk endpoints can be 8, 16, 32, or 64 bytes for full-speed devices,
and 512 bytes for high-speed devices.
It is best to view the USB descriptors as a hierarchical structure with four levels:
There is only one device descriptor for each USB device. Each device has one or more
configurations, each configuration has one or more interfaces, and each interface has zero or more
endpoints, as demonstrated in Figure 3.3 below.
• Device Level: The device descriptor includes general information about the USB device, i.e.,
global information for all of the device configurations. The device descriptor identifies, among
other things, the device class (HID device, hub, locator device, etc.), subclass, protocol code,
vendor ID, device ID and more. Each USB device has one device descriptor.
• Configuration Level: A USB device has one or more configuration descriptors. Each
descriptor identifies the number of interfaces grouped in the configuration and the power
attributes of the configuration (such as self-powered, remote wakeup, maximum power
consumption and more). Only one configuration can be loaded at a given time. For example,
an ISDN adapter might have two different configurations, one that presents it with a single
interface of 128 Kb/s and a second that presents it with two interfaces of 64 Kb/s each.
• Interface Level: The interface is a related set of endpoints that present a specific functionality
or feature of the device. Each interface may operate independently. The interface descriptor
describes the number of the interface, the number of endpoints used by this interface
and the interface-specific class, subclass and protocol values when the interface operates
independently.
In addition, an interface may have alternate settings. The alternate settings allow the endpoints
or their characteristics to be varied after the device is configured.
• Endpoint Level: The lowest level is the endpoint descriptor, which provides the host with
information regarding the endpoint's data transfer type and maximum packet size. For
isochronous endpoints, the maximum packet size is used to reserve the required bus time for
the data transfer — i.e., the bandwidth. Other endpoint attributes are its bus access frequency,
endpoint number, error handling mechanism and direction. The same endpoint can have
different properties (and consequently different uses) in different alternate settings.
Seems complicated? Not at all! WinDriver automates the USB configuration process. The
included DriverWizard utility [5] and USB diagnostics application scan the USB bus, detect all
USB devices and their configurations, interfaces, alternate settings and endpoints, and enable you
to pick the desired configuration before starting driver development.
WinDriver identifies the endpoint transfer type as determined in the endpoint descriptor. The
driver created with WinDriver contains all configuration information acquired at this early stage.
The driver code developed with WinDriver USB is binary compatible across the supported
Windows platforms — Windows 10/8.1/Server 2012 R2/8/Server 2012/7/Server 2008 R2/Server
2008 — and source code compatible across all supported operating systems — Windows 10/8.1/
Server 2012 R2/8/Server 2012/7/Server 2008 R2/Server 2008, Embedded Windows 8.1/8/7,
Windows CE (a.k.a. Windows Embedded Compact) 4.x–8.x (including Windows Mobile),
and Linux. For an up-to-date list of supported operating systems, visit Jungo's web site —
http://www.jungo.com.
WinDriver USB is a generic tool kit that supports all USB devices from all vendors and with all
types of configurations.
WinDriver USB encapsulates the USB specification and architecture, letting you focus on your
application logic. WinDriver USB features the graphical DriverWizard utility [5], which enables
you to easily detect your hardware, view its configuration information, and test it, before writing
a single line of code: DriverWizard first lets you choose the desired configuration, interface
and alternate setting combination, using a friendly graphical user interface. After detecting and
configuring your USB device, you can proceed to test the communication with the device —
perform data transfers on the pipes, send control requests, reset the pipes, etc. — in order to
ensure that all your hardware resources function as expected.
After your hardware is diagnosed, you can use DriverWizard to automatically generate your
device driver source code in C, Visual Basic .NET, or C#. WinDriver USB provides user-mode
APIs, which you can call from within your application in order to implement the communication
with your device. The WinDriver USB API includes USB-unique operations such as reset of
a pipe or a device. The generated DriverWizard code implements a diagnostics application,
which demonstrates how to use WinDriver's USB API to drive your specific device. In order to
use the application you just need to compile and run it. You can jump-start your development
cycle by using this application as your skeletal driver and then modifying the code, as needed, to
implement the desired driver functionality for your specific device.
DriverWizard also automates the creation of an INF file that registers your device to work with
WinDriver, which is an essential step in order to correctly identify and handle USB devices
using WinDriver. For an explanation on why you need to create an INF file for your USB device,
refer to Section 11.1.1 of the manual. For detailed information on creation of INF files with
DriverWizard, refer to Section 5.2 (see specifically Step 3).
With WinDriver USB, all development is done in the user mode, using familiar development and
debugging tools and your favorite compiler or development environment (such as MS Visual
Studio, MS eMbedded Visual C++, MS Platform Builder C++, GCC, Windows GCC).
For more information regarding implementation of USB transfers with WinDriver, refer to
Chapter 8 of the manual.
There are two layers responsible for abstracting the USB device to the USB device driver. The
upper layer is the USB Driver (USBD) layer, which includes the USB Hub Driver and the USB
Core Driver. The lower level is the Host Controller Driver (HCD) layer. The division of duties
between the HCD and USBD layers is not defined and is operating system dependent. Both the
HCD and USBD are software interfaces and components of the operating system, where the HCD
layer represents a lower level of abstraction.
The HCD is the software layer that provides an abstraction of the host controller hardware, while
the USBD provides an abstraction of the USB device and the data transfer between the host
software and the function of the USB device.
The USBD communicates with its clients (the specific device driver, for example) through
the USB Driver Interface (USBDI). At the lower level, the Core Driver and USB Hub Driver
implement the hardware access and data transfer by communicating with the HCD using the Host
Controller Driver Interface (HCDI).
The USB Hub Driver is responsible for identifying the addition and removal of devices from a
particular hub. When the Hub Driver receives a signal that a device was attached or detached, it
uses additional host software and the USB Core Driver to recognize and configure the device. The
software implementing the configuration can include the hub driver, the device driver, and other
software.
WinDriver USB abstracts the configuration procedure and hardware access described above
for the developer. With WinDriver's USB API, developers can perform all the hardware-
related operations without having to master the lower-level implementation for supporting these
operations.
• IDE:
For Windows CE 6.x: Microsoft Visual Studio 2005/2008 with a corresponding target SDK
or with the Windows CE 6.0 plugin
For Windows CE 7.x: Microsoft Visual Studio 2008 with the Windows Embedded Compact
7 plugin
For Windows CE 8.x: Microsoft Visual Studio 2012 or higher with the Application Builder
for Windows Embedded Compact 2013 plugin
32-bit x86
Jungo strives to support new Linux kernel versions as close as possible to their release.
To find out the latest supported kernel version, refer to the WinDriver release notes
(found online at http://www.jungo.com/st/support/windriver/wdver/).
• A GCC compiler
The version of the GCC compiler should match the compiler version used for building
the running Linux kernel.
• The following libraries are required for running GUI WinDriver application (e.g.,
DriverWizard [5]; Debug Monitor [7.2]):
- libstdc++.so.6
- libpng12.so.0
- libQtGui.so.4
- libQtCore.so.4
- libQtNetwork.so.4
1. Run the WinDriver installation — WD1251.EXE — and follow the installation instructions.
2. At the end of the installation, you may be prompted to reboot your computer.
To register your copy of WinDriver with the license you received from Jungo, follow these steps:
4. Select the Register WinDriver option from the File menu, and insert the license string you
received from Jungo.
6. To register source code that you developed during the evaluation period, refer to the
documentation of WDU_Init() [B.4.1].
• We recommend that you read Microsoft's documentation and understand the Windows
CE and device driver integration procedure before you perform the installation.
When defining ID values, take care to use the correct format, as specified in the
project_wd.reg comments — decimal in the case of USB devices.
This step is only necessary if you want the WinDriver CE kernel file
(windrvr1251.dll) to be a permanent part of the Windows CE image (NK.BIN),
which is the case if you select to transfer the file to your target platform using a
boot disk. If you prefer to have the file windrvr1251.dll loaded on demand via
the CESH/PPSH services, you do not need to perform this step until you build a
permanent kernel.
4. Select Make Run-Time Image from the Build menu to save the new image (NK.BIN).
5. Download your new kernel to the target platform and initialize it either by selecting
Attach Device from the Target menu, or by using a boot disk. For Windows CE 4.x, the
menu is called Download/Initialize rather than Attach Device.
6. Restart your target CE platform. The WinDriver CE kernel will automatically load.
7. Compile and run the sample programs to make sure that WinDriver CE is loaded and is
functioning correctly (see Section 4.4.2, which describes how to check your installation).
The following instructions apply to driver developers who do not build the Windows CE kernel,
but only download their drivers, built using MS eMbedded Visual C++ or MS Visual Studio
2005/2008 to a ready-made Windows CE platform.
1. Run the WinDriver installation — WD1251CE.EXE — on your host Windows PC, and
complete the installation.
When defining ID values, take care to use the correct format, as specified in the
project_wd.reg comments — decimal in the case of USB devices.
• On many versions of Windows CE, the operating system's security scheme prevents the
loading of unsigned drivers at boot time, therefore the WinDriver kernel module has to
be reloaded after boot. To load WinDriver on the target Windows CE platform every time
the OS is started, copy the WinDriver\redist\Windows_Mobile_5_ARMV4I\wdreg.exe
utility to the Windows\StartUp directory on the target PC.
4. Restart your target CE computer. The WinDriver CE kernel will automatically load. You will
have to do a warm reset rather than just suspend/resume (use the reset or power button on
your target CE computer).
5. Compile and run the sample programs to make sure that WinDriver CE is loaded and is
functioning correctly (see Section 4.4, which describes how to check your installation).
Note that if you install the WinDriver Windows toolkit on the same host PC, the installation will
override the value of the WD_BASEDIR variable from the Windows CE installation.
Therefore, before you install WinDriver for Linux, verify that the Linux source code and the file
version.h are installed on your machine:
• If you have yet to install Linux, install it, including the kernel source code, by following the
instructions for your Linux distribution.
• If Linux is already installed on your machine, check whether the Linux source code was
installed. You can do this by looking for 'linux' in the /usr/src directory. If the source code
is not installed, either install it, or reinstall Linux with the source code, by following the
instructions for your Linux distribution.
Install version.h:
• The file version.h is created when you first compile the Linux kernel source code.
Some distributions provide a compiled kernel without the file version.h. Look under
/usr/src/linux/include/linux to see whether you have this file. If you do not, follow these steps:
3. Type:
# make xconfig
5. Type:
# make dep
To run GUI WinDriver applications (e.g., DriverWizard [5]; Debug Monitor [7.2]) you must also
have version 6.0 of the libstdc++ library — libstdc++.so.6 — and version 12.0 of the libpng
library — libpng12.so.0. If you do not have these files, install the relevant packages for your
Linux distribution (e.g., libstdc++6 and libpng12-0). Also required is the libqtgui4 package.
Before proceeding with the installation, you must also make sure that you have a linux symbolic
link. If you do not, create one by typing
/usr/src$ ln -s <target kernel> linux
For example, for the Linux 3.0 kernel type
/usr/src$ ln -s linux-3.0/ linux
4.2.3.2. Installation
1. On your development Linux machine, change directory to your preferred installation
directory, for example to your home directory:
$ cd ~
The path to the installation directory must not contain any spaces.
3. Change directory to your WinDriver redist directory (the tar automatically creates a
WinDriver directory):
$ cd <WinDriver directory path>/redist
4. Install WinDriver:
• The configuration script creates a makefile based on the running kernel. You
may select to use another installed kernel source, by executing the script with
the --with-kernel-source=<path> option, where <path> is the full
path to the kernel source directory — e.g., /usr/src/linux.
• If the Linux kernel version is 2.6.26 or higher, the configuration script generates
makefiles that use kbuild to compile the kernel modules. You can force the use
of kbuild on earlier versions of Linux, by executing the configuration script
with the --enable-kbuild flag.
For a full list of the configuration script options, use the --help option:
./configure --help
5. Create a symbolic link so that you can easily launch the DriverWizard GUI:
$ ln -s <path to WinDriver>/wizard/wdwizard /usr/bin/wdwizard
6. Change the read and execute permissions on the file wdwizard so that ordinary users can
access this program.
7. Change the user and group IDs and give read/write permissions to the device file
/dev/windrvr1251, depending on how you wish to allow users to access hardware
through the device. Due to security reasons, by default the device file is created
with permissions only for the root user. Change the permissions by modifying your
/etc/udev/permissions.d/50-udev.permissions file. For example, add the following line to
provide read and write permissions:
windrvr1251:root:root:0666
8. Define a new WD_BASEDIR environment variable and set it to point to the location of your
WinDriver directory, as selected during the installation. This variable is used in the make and
source files of the WinDriver samples and generated DriverWizard [5] code, and is also used
to determine the default directory for saving your generated DriverWizard projects. If you do
not define this variable you will be instructed to do so when attempting to build the sample/
generated code using the WinDriver makefiles.
10. You can now start using WinDriver to access your hardware and generate your driver code!
Use the WinDriver/util/wdreg script to load the WinDriver kernel module [9.3].
To register your copy of WinDriver with the license you received from Jungo, follow these steps:
13. Select the Register WinDriver option from the File menu, and insert the license string you
received from Jungo.
15. To register source code that you developed during the evaluation period, refer to the
documentation of WDU_Init() [B.4.1].
For security reasons the WinDriver installation script does not automatically perform the
steps of changing the permissions on /dev/windrvr1251 and the DriverWizard application
(wdwizard).
After the installation, start DriverWizard and enter the new license string, if you have received
one. This completes the minimal upgrade steps.
• Pass the new license string as a parameter to WDU_Init() [B.4.1] (or to WD_License(),
when using the old WD_UsbXXX() APIs).
• Verify that the call to WD_DriverName() [B.1] in your driver code (if exists) uses the name
of the new driver module — windrvr1251 or your renamed version of this driver [11.2].
If you use the generated DriverWizard code or one of the samples from the new WinDriver
version, the code will already use the default driver name from the new version. Also, if your
code is based on generated/sample code from an earlier version of WinDriver, rebuilding the
code with windrvr.h from the new version is sufficient to update the code to use the new
default driver-module name (due to the use of the WD_DEFAULT_DRIVER_NAME_BASE
definition).
If you elect to rename the WinDriver driver module [11.2], ensure that your code calls
WD_DriverName() [B.1] with your custom driver name. If you rename the driver from the
new version to a name already used in your old project, you do not need to modify your code.
2. If you are a registered user, make sure that your WinDriver license is registered (refer to
Section 4.2, which explains how to install WinDriver and register your license).
If you are an evaluation version user, you do not need to register a license.
2. Run the Debug Monitor with the status command on the target device:
wddebug.exe status
If the WinDriver installation was successful, the application will display information
regarding the Debug Monitor version and current status, the running WinDriver kernel
module, and general system information.
• wdreg.exe and wdreg_gui.exe are found in the WinDriver\util directory (see Chapter 9
for details regarding these utilities).
1. Close any open WinDriver applications, including DriverWizard, the Debug Monitor, and
user-specific applications.
2. Uninstall all Plug-and-Play devices (USB/PCI) that have been registered with WinDriver via
an INF file:
• Verify that no INF files that register your device(s) with WinDriver's kernel module
(windrvr1251.sys) are found in the %windir%\inf directory.
3. Uninstall WinDriver:
The uninstall will stop and unload the WinDriver kernel module (windrvr1251.sys); delete
the copy of the windrvr1251.inf file from the %windir%\inf directory; delete WinDriver
from Windows' Start menu; delete the WinDriver installation directory (except for files
that you added to this directory); and delete the shortcut icons to the DriverWizard and
Debug Monitor utilities from the Desktop.
• On a target PC, on which you installed the WinDriver kernel module (windrvr1251.sys),
but not the entire WinDriver toolkit:
Use the wdreg utility to stop and unload the driver:
wdreg -inf <path to windrvr1251.inf> uninstall
When running this command, windrvr1251.sys should reside in the same directory
as windrvr1251.inf.
(On the development PC, the relevant wdreg uninstall command is executed for you by the
uninstall utility).
• If you attempt to uninstall WinDriver while there are open handles to the WinDriver
service (windrvr1251.sys or your renamed driver [11.2], or there are connected and
enabled Plug-and-Play devices that are registered to work with this service, wdreg
will fail to uninstall the driver. This ensures that you do not uninstall the driver while
it is being used.
• You can check if the WinDriver kernel module is loaded by running the Debug
Monitor utility (WinDriver\util\wddebug_gui.exe) [7.2]. When the driver is loaded,
the Debug Monitor log displays driver and OS information; otherwise, it displays a
relevant error message. On the development PC, the uninstall command will delete
the Debug Monitor executables; to use this utility after the uninstallation, create a
copy of wddebug_gui.exe before performing the uninstall procedure.
4. If windrvr1251.sys was successfully unloaded, erase the following files (if they exist):
• %windir%\system32\drivers\windrvr1251.sys
• %windir%\inf\windrvr1251.inf
• %windir%\system32\wdapi1251.dll
1. Verify that the WinDriver driver modules are not being used by another program:
• View the list of modules and the programs using each of them:
# /sbin/lsmod
• Identify any applications and modules that are using the WinDriver driver modules. (By
default, WinDriver module names begin with windrvr1251).
• Close any applications that are using the WinDriver driver modules.
5. If you created a symbolic link to DriverWizard, remove the link using the command
# rm -f /usr/bin/wdwizard
5.1. An Overview
DriverWizard (included in the WinDriver toolkit) is a graphical user interface (GUI) tool that is
targeted at two major phases in the hardware and driver development:
• Hardware diagnostics — DriverWizard enables you to write and read hardware resources
before writing a single line of code. After the hardware has been built, attach your device to
a USB port on your machine, view its configuration and pipes information, and verify the
hardware's functionality by transferring data on the pipes, sending standard requests on the
control pipe, and resetting the pipes.
• Code generation — Once you have verified that the device is operating to your satisfaction,
use DriverWizard generate skeletal driver source code with functions to view and access your
hardware's resources.
On Windows, DriverWizard can also be used to generate an INF file [11.1] for your hardware.
• Library functions for accessing each element of your device's resources (memory ranges, I/O
ranges, registers and interrupts).
• A 32-bit diagnostics program in console mode with which you can diagnose your device.
This application utilizes the special library functions described above. Use this diagnostics
program as your skeletal device driver.
• A project solution that you can use to automatically load all of the project information and
files into your development environment.
For Linux, DriverWizard generates the required makefile.
If you don't need to generate and install an INF file, skip this step.
To generate and install the INF file with DriverWizard, do the following:
a. In the Select Your Device screen (see Step 2), click the Generate .INF file button or
click Next.
b. DriverWizard will display information detected for your device — Vendor ID, Product
ID, Device Class, manufacturer name and device name — and allow you to modify this
information
c. For multiple-interface USB devices, you can select to generate an INF file either for the
composite device or for a specific interface.
d. When you are done, click Next and choose the directory in which you wish to store the
generated INF file. DriverWizard will then automatically generate the INF file for you.
You can choose to automatically install the INF file by checking the Automatically
Install the INF file option in the DriverWizard's INF generation dialogue.
If the automatic INF file installation fails, DriverWizard will notify you and provide
manual installation instructions (refer also the manual INF file installation instructions in
Section 11.1).
e. When the INF file installation completes, select and open your device from the list in the
Select Your Device screen.
In order for WinDriver to correctly identify the resouces of a USB device and
communicate with it — including for the purpose of the DriverWizard device
diagnostics outlined in the next step — the deivce must be registered to work with
WinDriver via an INF file (see Step 3).
a. In the Select Your Device screen (see Step 2), click the Uninstall .INF file button.
DriverWizard detects all the device's supported alternate settings and displays them, as
demonstrated in Figure 5.6 below.
Select the desired alternate setting from the displayed list.
DriverWizard will display the pipes information for the selected alternate setting.
For USB devices with only one alternate setting configured, DriverWizard
automatically selects the detected alternate setting and therefore the Select Device
Interface dialogue will not be displayed.
a. Test your USB device's pipes: DriverWizard shows the pipes detected for the selected
alternate setting. To perform USB data transfers on the pipes, follow these steps:
ii. For a control pipe (a bidirectional pipe), click Read / Write. A new dialogue will
appear, allowing you to select a standard USB request or define a custom request, as
demonstrated in Figure 5.7.
When you select one of the available standard USB requests, the setup packet
information for the selected request is automatically filled and the request
description is displayed in the Request Description box.
For a custom request, you are required to enter the setup packet information and
write data (if exists) yourself. The size of the setup packet should be eight bytes and
it should be defined using little endian byte ordering. The setup packet information
should conform to the USB specification parameters (bmRequestType,
bRequest, wValue, wIndex, wLength).
iii. For an input pipe (moves data from device to host) click Listen to Pipe. To
successfully accomplish this operation with devices other than HID, you need to
first verify that the device sends data to the host. If no data is sent after listening for
a short period of time, DriverWizard will notify you that the Transfer Failed.
iv. For an output pipe (moves data from host to device), click Write to Pipe. A new
dialogue box will appear asking you to enter the data to write. The DriverWizard log
will contain the result of the operation.
v. You can reset input and output pipes by pressing the Reset Pipe button for the
selected pipe.
a. Select to generate code either via the Generate Code toolbar icon or from the Project |
Generate Code menu.
b. In the Select Code Generation Options dialogue box that will appear, choose the code
language and development environment(s) for the generated code and select Next to
generate the code.
c. Save your project (if required) and click OK to open your development environment
with the generated driver.
d. Close DriverWizard.
• Use this code as a starting point for your device driver. Modify where needed to perform
your driver's specific functionality.
• The source code DriverWizard creates can be compiled with any 32-bit compiler, and will
run on all supported platforms without modification.
You can also build the generated code using any other compiler or development environment that
supports the selected code language and target OS. Simply create a new project or make file for
your selected compiler/environment, include the generated source files, and run the code.
• For Windows, the generated compiler/environment files are located under an x86
directory — for 32-bit projects — or an amd64 directory — for 64-bit projects.
• For Windows CE, note that the generated Windows Mobile code is targeted at the
Windows Mobile 5.0/6.0 ARMV4I SDK.
• Use DriverWizard to generate skeletal code for your device in C, Visual Basic .NET, or C#.
For more information about DriverWizard, refer to Chapter 5.
• Use any C or .NET compiler or development environment (depending on the code you created)
to build the skeletal driver you need.
WinDriver provides specific support for the following environments and compilers: MS Visual
Studio, MS eMbedded Visual C++, MS Platform Builder C++, GCC, Windows GCC
When using the WDU_xxx WinDriver USB API [B.2], include the wdu_lib.h header file;
(this file already includes windrvr.h).
Include any other header file that provides APIs that you wish to use from your code (e.g.,
files from the WinDriver/samples/shared directory, which provide convenient diagnostics
functions.)
2. Include the relevant header files from your source code: For example, to use the USB API
from the wdu_lib.h header file, add the following line to the code:
#include "wdu_lib.h"
3. Link your code with the WDAPI library (Windows) / shared object (Linux):
You can also include the library's source files in your project instead of linking the project
with the library. The C source files are located under the WinDriver/src/wdapi directory.
When linking your project with the WDAPI library/shared object, you will need to
distribute this binary with your driver.
For Windows, get wdapi1251.dll / wdapi1251_32.dll (for 32-bit applications targeted
at 64-bit platforms) from the WinDriver\redist directory.
For Linux, get libwdapi1251.so / libwdapi1251_32.so (for 32-bit applications targeted
at 64-bit platforms) from the WinDriver/lib directory.
Note: On Windows and Linux, when using the DLL/shared object file for 32-bit applications
on 64-bit platforms (wdapi1251_32.dll / libwdapi1251_32.so), rename the copy of the file in
the distribution package, by removing the _32 portion [A.2].
For detailed distribution instructions, refer to Chapter 10.
4. Add any other WinDriver source files that implement API that you which to use in your code
(e.g., files from the WinDriver/samples/shared directory.)
2. Once the attach callback is received, you can start using one of the
WDU_Transfer() [B.4.8.1] functions family to send and receive data.
When developing a driver for a 64-bit platform [A], your project or makefile must include
the KERNEL_64BIT preprocessor definition. In the makefiles, the definition is added using
the -D flag: -DKERNEL_64BIT. (The sample and wizard-generated Linux and Windows
GCC makefiles and the Windows MS Visual Studio projects, in the 64-bit WinDriver
toolkit, already include this definition.)
Before building your code, verify that the WD_BASEDIR environment variable is set to the
location of the of the WinDriver installation directory.
On Windows, Windows CE, and Linux you can define the WD_BASEDIR environment
variable globally — as explained in Chapter 4: For Windows — refer to the Windows
WD_BASEDIR note in Section 4.2.1; for Windows CE — refer to Section 4.2.2.3; for
Linux: refer to Section 4.2.3.2, Step 8.
To register the device with WinDriver, use either of the following methods:
• Modify the registry to identify your device and link it to windrvr1251.dll. The registry can be
modified by adding the relevant information to your project.reg file.
To identify the device by its vendor ID (<VID>) and product ID (<PID>) — as decimal
values — add the following:
[HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\<VID>_<PID>\Default\Default\WDR]
"DLL"="windrvr1251.dll"
To identify the device by its USB class (<CLASS>), subclass (<SUBCLASS>), and protocol
(<PROT>) — as decimal values — add the following:
[HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\Default\Default\<CLASS>_<SUBCLASS>_<PROT>\WDR]
"DLL"="windrvr1251.dll"
• Call WDU_Init() to identify the device by its vendor and product IDs and register it with
WinDriver, before connecting the device to the computer .
For more information about the relevant registry settings, refer to USB Driver Registry
Settings in the MSDN Library.
• The Debug Monitor utility [7.2] logs debug messages from WinDriver's kernel-mode and user-
mode APIs. You can also use WinDriver APIs to send your own debug messages to the Debug
Monitor log.
• Use DriverWizard to validate your device's USB configuration and test the communication
with the device.
In addition, WinDriver enables you to print your own debug messages to the Debug Monitor,
using the WD_DebugAdd() function [B.6.6] or the high-level PrintDbgMessage()
function [B.7.14].
• wddebug [7.2.2] — a console-mode version for Windows, Windows CE, and Linux; on
Windows CE, wddebug also supports GUI execution.
• Run WinDriver/util/wddebug_gui
2. Set the Debug Monitor's status, trace level and debug sections information from the Debug
Options dialogue, which is activated either from the Debug Monitor's View | Debug Options
menu or the Debug Options toolbar button.
• Section — Choose what part of the WinDriver API you would like to monitor.
Choose carefully those sections that you would like to monitor. Checking more
options than necessary could result in an overflow of information, making it harder
for you to locate your problem.
• Level — Choose the level of messages you want to see for the resources defined.
Error is the lowest trace level, resulting in minimum output to the screen.
Trace is the highest trace level, displaying every operation the WinDriver kernel
performs.
Select this option to send the debug messages received from the WinDriver kernel module
to an external kernel debugger, in addition to the Debug Monitor.
On Windows 7 and higher, the first time that you enable this option you will need
to restart the PC.
A free Windows kernel debugger, WinDbg, is distributed with the Windows Driver
Kit (WDK) and is part of the Debugging Tools for Windows package, distributed via
the Microsoft web site.
3. Once you have defined what you want to trace and on what level, click OK to close the
Debug Options window.
4. Optionally make additional configurations via the Debug Monitor menus and toolbar.
When debugging OS crashes or hangs, it's useful to auto-save the Debug Monitor log,
via the File –> Toggle Auto-Save menu option (available also via a toolbar icon), in
addition to sending the debug messages to the OS kernel debugger (see Step 2).
You can use the Edit –> Add Custom Message... menu option (available also via a
toolbar icon) to add custom messages to the log. This is especially useful for clearly
marking different execution sections in the log.
6. Watch the Debug Monitor log (or the kernel debugger log, if enabled) for errors or any
unexpected messages.
The driver name should be set to the name of the driver file without the file's extension;
e.g., windrvr1251, not windrvr1251.sys (on Windows) or windrvr1251.o (on Linux).
For example, if you have renamed the default windrvr1251.sys driver on Windows to
my_driver.sys, you can log messages from your driver by running the Debug Monitor using the
following command: wddebug_gui my_driver
The wddebug arguments must be provided in the order in which they appear in the usage
statement above.
The driver name should be set to the name of the WinDriver kernel module — windrvr1251
(default), or a renamed version of this driver (refer to the explanation in Section 11.2).
The driver name should be set to the name of the driver file without the file's extension;
e.g., windrvr1251, not windrvr1251.sys (on Windows) or windrvr1251.o (on Linux).
Activation commands:
dbg_on — Redirect the debug messages from the Debug Monitor to a kernel debugger
and turn the Debug Monitor on (if it was not already turned on).
On Windows 7 and higher, the first time that you enable this option you will need
to restart the PC.
dbg_off — Stop redirecting debug messages from the Debug Monitor to a kernel
debugger.
The on and dbg_on commands can be used together with the <level> and
<sections> arguments.
dump — Continuously send ("dump") debug information to the command prompt, until the
user selects to stop (by following the instructions displayed in the command prompt).
clock_on — Add a timestamp to each debug message. The timestamps are relative to the
driver-load time, or to the time of the last clock_reset command.
The following arguments are applicable only with the on or dbg_on commands:
• <level> — The debug trace level to set — one of the following flags: ERROR, WARN, INFO,
or TRACE (default).
ERROR is the lowest trace level and TRACE is the highest level (displays all messages).
When the <sections> argument is set, the <level> argument must be set as well
(no default).
• <sections> — The debug sections — i.e., the WinDriver API sections — to monitor.
This argument can be set either to ALL (default) — to monitor all the supported debug sections
— or to a quoted string that contains a combination of any of the supported debug-section flags
(run 'wddebug help' to see the full list).
Usage Sequence
• Turn on the Debug Monitor by running wddebug with either the on or dbg_on command;
the latter redirects the debug messages to the OS kernel debugger before turning on the Debug
Monitor.
You can use the <level> and <sections> arguments to set the debug level and sections
for the log. If these arguments are not explicitly set, the default values will be used; (note that if
you set the sections you must also set the level).
You can also log messages from a renamed WinDriver driver by preceding the command with
the name of the driver (default: windrvr1251) — see the <driver_name> argument.
• If you did not select to redirect the debug messages to the OS kernel debugger (using the
dbg_on command), run wddebug with the dump command to begin dumping debug
messages to the command prompt.
You can turn off the display of the debug messages, at any time, by following the instructions
displayed in the command prompt.
• Run applications that use the driver, and view the debug messages as they are being logged to
the command prompt/the kernel debugger.
• At any time while the Debug Monitor is running, you can run wddebug with the following
commands:
dbg_on and dbg_off — to toggle the redirection of debug messages to the OS kernel
debugger
dump — to start a new dump of the debug log to the command prompt; (the dump can be
stopped at any time by following the instructions in the prompt)
• When you are ready, turn off the Debug Monitor by running wddebug with the off command.
The status command can be used to view information regarding the running
WinDriver driver even when the Debug Monitor is off.
Example
• Turn the Debug Monitor on with the highest trace level for all sections:
wddebug on TRACE ALL
This is the same as running 'wddebug on TRACE', because ALL is the default
<sections> value.
• Dump the debug messages continuously to the command prompt or a file, until the user selects
to stop:
wddebug dump
wddebug dump <filename>
• Use the driver and view the debug messages in the command prompt.
When executing wddebug without arguments, the user is informed, via a GUI message box, that
log messages will be stored in a predetermined log file — wdlog.txt in the root Windows CE
directory — and is given the option to cancel or continue.
Figure 7.3. wddebug Windows CE Start Log Message
If the user selects to continue, debug logging is turned on with a trace level of TRACE and debug
sections ALL, and the Debug Monitor begins dumping debug messages to the wdlog.txt log
file. The user can stop the logging and turn off debug logging, at any time, via a dedicated GUI
message box.
Figure 7.4. wddebug Windows CE Stop Log Message
As explained in Section 3.5, the USB standard supports two kinds of data exchange between the
host and the device — control exchange and functional data exchange.
The WinDriver APIs enable you to implement both control and functional data transfers.
Figure 8.1 demonstrates how a device's pipes are displayed in the DriverWizard utility, which
enables you to perform transfers from a GUI environment.
Section 8.2 below provides detailed information regarding USB control transfers and how they
can be implemented using WinDriver.
Section 8.3 describes the functional data transfer implementation options provided by WinDriver.
During the setup stage, an 8-byte setup packet is used to transmit information to the control
endpoint of the device (endpoint 0). The setup packet's format is defined by the USB
specification.
A control transfer can be a read transaction or a write transaction. In a read transaction the setup
packet indicates the characteristics and amount of data to be read from the device. In a write
transaction the setup packet contains the command sent (written) to the device and the number of
control data bytes that will be sent to the device in the data stage.
Refer to Figure 8.2 (taken from the USB specification) for a sequence of read and write
transactions.
'(in)' indicates data flow from the device to the host.
'(out)' indicates data flow from the host to the device.
bRequest Value
GET_STATUS 0
CLEAR_FEATURE 1
Reserved for future use 2
SET_FEATURE 3
Reserved for future use 4
SET_ADDRESS 5
GET_DESCRIPTOR 6
SET_DESCRIPTOR 7
GET_CONFIGURATION 8
SET_CONFIGURATION 9
GET_INTERFACE 10
SET_INTERFACE 11
SYNCH_FRAME 12
The following setup packet is for a control read transaction that retrieves the device descriptor
from the USB device. The device descriptor includes information such as USB standard revision,
vendor ID and product ID.
80 06 00 01 00 00 12 00
0h=0000b
In response, the device sends the device descriptor data. A device descriptor of the Cypress
EZ-USB Integrated Circuit is provided as an example:
Byte No. 0 1 2 3 4 5 6 7 8 9 10
Content 12 01 00 01 ff ff ff 40 47 05 80
Byte No. 11 12 13 14 15 16 17
Content 00 01 00 00 00 00 01
As defined in the USB specification, byte 0 indicates the length of the descriptor, bytes 2-3
contain the USB specification release number, byte 7 is the maximum packet size for the control
endpoint (endpoint 0), bytes 8-9 are the vendor ID, bytes 10-11 are the product ID, etc.
2. You can either enter a custom setup packet, or use a standard USB request.
• For a custom request: enter the required setup packet fields. For a write transaction that
includes a data stage, enter the data in the Write to pipe data (Hex) field. Click Read
From Pipe or Write To Pipe according to the required transaction (see Figure 8.3).
• For a standard USB request: select a USB request from the requests list, which includes
requests such as GET_DESCRIPTOR CONFIGURATION, GET_DESCRIPTOR
DEVICE, GET_STATUS DEVICE, etc. (see Figure 8.4). The description of the selected
request will be displayed in the Request Description box on the right hand of the dialogue
window.
3. The results of the transfer, such as the data that was read or a relevant error, are displayed in
DriverWizard's Log window.
Figure 8.5, below, shows the contents of the Log window after a successful
GET_DESCRIPTOR DEVICE request.
Fill the setup packet in the BYTE SetupPacket[8] array and call these functions to send
setup packets on the control pipe (pipe 0) and to retrieve control and status data from the device.
• The following sample demonstrates how to fill the SetupPacket[8] variable with a
GET_DESCRIPTOR setup packet:
setupPacket[0] = 0x80; /* BmRequstType */
setupPacket[1] = 0x6; /* bRequest [0x6 == GET_DESCRIPTOR] */
setupPacket[2] = 0; /* wValue */
setupPacket[3] = 0x1; /* wValue [Descriptor Type: 0x1 == DEVICE] */
setupPacket[4] = 0; /* wIndex */
setupPacket[5] = 0; /* wIndex */
setupPacket[6] = 0x12; /* wLength [Size for the returned buffer] */
setupPacket[7] = 0; /* wLength */
• The following sample demonstrates how to send a setup packet to the control pipe (a GET
instruction; the device will return the information requested in the pBuffer variable):
WDU_TransferDefaultPipe(hDev, TRUE, 0, pBuffer, dwSize,
bytes_transferred, &setupPacket[0], 10000);
• The following sample demonstrates how to send a setup packet to the control pipe (a SET
instruction):
WDU_TransferDefaultPipe(hDev, FALSE, 0, NULL, 0,
bytes_transferred, &setupPacket[0], 10000);
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.1] 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.
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.
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.
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 successfully unload your driver, make sure that there are no open handles to the
WinDriver service (windrvr1251.sys or your renamed driver [11.2]), and that there are no
connected and enabled Plug-and-Play devices that are registered with this service.
The WinDriver Windows kernel module — windrvr1251.sys — is a fully WDM driver, which
can be installed using the wdreg utility, as explained in the following sections.
This section describes the use of wdreg/ wdreg_gui on Windows operating systems.
2. The explanations and examples below refer to wdreg, but any references to wdreg can
be replaced with wdreg_gui.
9.2.1.1. Overview
This section explains how to use the wdreg utility to install the WDM windrvr1251.sys driver, or
to install INF files that register USB devices to work with this driver, on Windows.
You can rename the windrvr1251.sys kernel module and modify your device INF file to
register with your renamed driver, as explained in Section 11.2.1. To install your modified
INF files using wdreg, simply replace any references to windrvr1251 below with the name
of your new driver.
Usage: The wdreg utility can be used in two ways as demonstrated below:
• OPTIONS
wdreg supports several basic OPTIONS from which you can choose one, some, or none:
-rescan <enumerator> — Rescan enumerator (ROOT, USB, etc.) for hardware changes.
Only one enumerator can be specified.
-compat — Use the traditional SetupDi API instead of the newer Driver Install Frameworks
API (DIFxAPI).
• ACTIONS
wdreg supports several basic ACTIONS:
install — Installs the INF file, copies the relevant files to their target locations, and
dynamically loads the driver specified in the INF file name by replacing the older version (if
needed).
uninstall — Removes your driver from the registry so that it will not load on next boot (see
note below).
disable — Disables your driver, i.e., dynamically unloads it, but the driver will reload after
system boot (see note below).
To successfully disable/uninstall your driver, make sure that there are no open handles to
the WinDriver service (windrvr1251.sys or your renamed driver [11.2]), and that there are
no connected and enabled Plug-and-Play devices that are registered with this service.
You can replace the install option in the example above with preinstall to pre-install
the device INF file for a device that is not currently connected to the PC.
To unload the driver/INF file, use the same commands, but simply replace install in the
examples above with uninstall.
To automatically load WinDriver on each boot, add the following line to the target's Linux
boot file (for example, /etc/rc.local):
<path to wdreg> windrvr1251
On many versions of Windows CE, the operating system's security scheme prevents the
loading of unsigned drivers at boot time, therefore the WinDriver kernel module has to be
reloaded after boot. To load WinDriver on the target Windows CE platform every time the
OS is started, copy the wdreg.exe utility to the Windows\StartUp directory on the target
PC.
The source code of the Windows CE wdreg.exe utility is available under the
WinDriver\samples\wince_install\wdreg directory on the development PC.
• If you have created new INF and/or catalog files for your driver, replace the references
to the original WinDriver INF files and/or to the windrvr1251.cat catalog file with
the names of your new files (see the file renaming information in Sections 11.2.1 and
11.3.2).
Distributing the driver you created is a multi-step process. First, create a distribution package
that includes all the files required for the installation of the driver on the target computer.
Second, install the driver on the target machine. This involves installing windrvr1251.sys and
windrvr1251.inf, and installing the specific INF file for your device.
Finally, you need to install and execute the hardware-control application that you developed with
WinDriver. These steps can be performed using wdreg utility.
If you wish to distribute drivers for both 32-bit and 64-bit target platforms, you must
prepare separate distribution packages for each platform. The required files for each
package are provided in the WinDriver installation directory for the respective platform.
• windrvr1251.sys.
Get this file from the WinDriver\redist directory of the WinDriver package.
• windrvr1251.inf.
Get this file from the WinDriver\redist directory of the WinDriver package.
• windrvr1251.cat
Get this file from the WinDriver\redist directory of the WinDriver package.
• wdapi1251.dll (for distribution of 32-bit binaries to 32-bit target platforms or for distribution
of 64-bit binaries to 64-bit platforms) or wdapi1251_32.dll (for distribution of 32-bit binaries
to 64-bit platforms [A.2].
Get this file from the WinDriver\redist directory of the WinDriver package.
Follow the instructions below in the order specified to properly install your driver on the target
computer:
• Preliminary Steps:
To successfully install your driver, make sure that there are no open handles to the WinDriver
service (windrvr1251.sys or your renamed driver [11.2]), and that there are no connected and
enabled Plug-and-Play devices that are registered with this service. If the service is being used,
attempts to install the new driver using wdreg will fail. This is relevant, for example, when
upgrading from an earlier version of the driver that uses the same driver name. You can disable
or uninstall connected devices from the Device Manager (Properties | Disable/Uninstall) or
using wdreg, or otherwise physically disconnect the device(s) from the PC.
Since v11.9.0 of WinDriver, the default driver module name includes the WinDriver
version, so if you do not rename the driver to a previously-used name there should not be
conflicts with older drivers.
For more information regarding driver digital signing and certification and the
signing of your WinDriver-based driver, refer to Section 11.3 of the manual.
2. Use the utility wdreg to install WinDriver's kernel module on the target computer:
wdreg -inf <path to windrvr1251.inf> install
You can find the executable of wdreg in the WinDriver package under the WinDriver\util
directory. For a general description of this utility and its usage, please refer to Chapter 9.
When distributing your driver, you should attempt to ensure that the installation
does not overwrite a newer version of windrvr1251.sys with an older version
of the file in Windows drivers directory (%windir%\system32\drivers) — for
example, by configuring your installation program (if you are using one) or your
INF file so that the installer automatically compares the time stamp on these two
files and does not overwrite a newer version with an older one. The provided
windrvr1251.inf file uses the COPYFLG_NO_VERSION_DIALOG directive,
which is designed to avoid overwriting a file in the destination directory with
the source file if the existing file is newer than the source file. There is also a
similar COPYFLG_OVERWRITE_OLDER_ONLY INF directive that is designed
to ensure that the source file is copied to the destination directory only if the
destination file is superseded by a newer version. Note, however, that both of
these INF directives are irrelevant to digitally signed drivers. As explained in the
Microsoft INF CopyFiles Directive documentation — http://msdn.microsoft.com/
en-us/library/ff546346%28v=vs.85%29.aspx — if a driver package is digitally
signed, Windows installs the package as a whole and does not selectively omit
files in the package based on other versions already present on the computer. The
windrvr1251.sys driver provided by Jungo is digitally signed (refer to Section 11.3
for more information).
• Install the INF file for your device (registering your Plug-and-Play device with
windrvr1251.sys):
Run the utility wdreg with the install command to automatically install the INF file and
update Windows Device Manager:
wdreg -inf <path to your INF file> install
You can also use the wdreg utility's preinstall command to pre-install an INF file for a
device that is not currently connected to the PC:
wdreg -inf <path to your INF file> preinstall
• Install wdapi1251.dll:
If your hardware-control application/DLL uses wdapi1251.dll (as is the case for the
sample and generated DriverWizard WinDriver projects), copy this DLL to the target's
%windir%\system32 directory.
If you are distributing a 32-bit application/DLL to a target 64-bit platform [A.2], rename
wdapi1251_32.dll in your distribution package to wdapi1251.dll, and copy the renamed file to
the target's %windir%\sysWOW64 directory.
If you attempt to write a 32-bit installation program that installs a 64-bit program, and
therefore copies the 64-bit wdapi1251.dll DLL to the %windir%\system32 directory,
you may find that the file is actually copied to the 32-bit %windir%\sysWOW64
directory. The reason for this is that Windows x64 platforms translate references to
64-bit directories from 32-bit commands into references to 32-bit directories. You can
avoid the problem by using 64-bit commands to perform the necessary installation steps
from your 32-bit installation program. The system64.exe program, provided in the
WinDriver\redist directory of the Windows x64 WinDriver distributions, enables you to
do this.
To distribute the driver you developed with WinDriver to a new target Windows CE platform,
follow these steps:
1. If you have not already done so, modify the project registry file —
WinDriver\samples\wince_install\project_wd.reg — to add an entry for your target device.
When defining ID values, take care to use the correct format, as specified in the
project_wd.reg comments — decimal in the case of USB devices.
This step is only necessary if you want the WinDriver CE kernel file
(windrvr1251.dll) to be a permanent part of the Windows CE image (NK.BIN),
which is the case if you select to transfer the file to your target platform using a
boot disk. If you prefer to have the file windrvr1251.dll loaded on demand via
the CESH/PPSH services, you do not need to perform this step until you build a
permanent kernel.
4. Select Make Run-Time Image from the Build menu to save the new image (NK.BIN).
5. Download your new kernel to the target platform and initialize it either by selecting
Attach Device from the Target menu, or by using a boot disk. For Windows CE 4.x, the
menu is called Download/Initialize rather than Attach Device.
6. Restart your target CE platform. The WinDriver CE kernel will automatically load.
When defining ID values, take care to use the correct format, as specified in the
project_wd.reg comments — decimal in the case of USB devices.
• On many versions of Windows CE, the operating system's security scheme prevents the
loading of unsigned drivers at boot time, therefore the WinDriver kernel module has to
be reloaded after boot. To load WinDriver on the target Windows CE platform every time
the OS is started, copy the WinDriver\redist\Windows_Mobile_5_ARMV4I\wdreg.exe
utility to the Windows\StartUp directory on the target PC.
3. Restart your target CE computer. The WinDriver CE kernel will automatically load. You will
have to do a warm reset rather than just suspend/resume (use the reset or power button on
your target CE computer).
• If you have renamed the WinDriver driver modules [11.2], replace references to
windrvr1251 in the following instructions with the name of your renamed driver module.
• It is recommended that you supply an installation shell script to automate the build and
installation processes on the target.
• If you wish to distribute drivers for both 32-bit and 64-bit target platforms, you must
prepare separate distribution packages for each platform. The required files for each
package are provided in the WinDriver installation directory for the respective platform.
• In the following instructions, <source_dir> represents the source directory from which
to copy the distribution files. The default source directory is your WinDriver installation
directory. However, if you have renamed the WinDriver driver modules [11.2], the
source directory is a directory containing modified files for compiling and installing
the renamed drivers; when using DriverWizard to generate the driver code, the source
directory for the renamed driver is the generated xxx_installation directory, where xxx is
the name of your generated driver project (see Section 11.2.2, Step 1).
Your kernel driver modules cannot be distributed as-is; they must be recompiled on each
target machine, to match the kernel version on the target. This is due to the following
reason: The Linux kernel is continuously under development, and kernel data structures
are subject to frequent changes. To support such a dynamic development environment,
and still have kernel stability, the Linux kernel developers decided that kernel modules
must be compiled with header files identical to those with which the kernel itself was
compiled. They enforce this by including a version number in the kernel header files, which
is checked against the version number encoded into the kernel. This forces Linux driver
developers to support recompilation of their driver with the target system's kernel version.
Following is a list of the components you need to distribute to enable compilation of your kernel
driver modules on the target machine.
It is recommended that you copy the files to subdirectories in the distribution directory
that match the source subdirectories, such as redist and include, except where otherwise
specified. If you select not do so, you will need to modify the file paths in the configuration
scripts and related makefile templates, to match the location of the files in your distribution
directory.
• From the <WinDriver installation directory>/util directory (or from the generated
DriverWizard xxx_installation/redist directory), copy wdreg — a script for loading the
WinDriver kernel driver modules (see Section 9.3) — to the redist distribution directory.
• From the <source_dir>/redist directory, unless where otherwise specified, copy the following
files:
setup_inst_dir — a script for installing the WinDriver driver modules, using wdreg (see
above).
linux_wrappers.c/.h — wrapper library source code files that bind the kernel module to the
Linux kernel.
linux_common.h and wdusb_interface.h — header files required for building the kernel
modules on the target.
The compiled object code for building the WinDriver kernel driver modules —
windrvr_gcc_v2.a — for GCC v2.x.x compilation; note that this file is not found in the
64-bit WinDriver installations, because 64-bit Linux architectures don't use GCC v2.
Configuration scripts and makefile templates for creating makefiles for building and
installing the WinDriver kernel driver modules.
Files that include .kbuild in their names use kbuild for the driver compilation.
configure — a configuration script that uses the makefile.in template to create a makefile
for building and installing the WinDriver driver modules, and executes the configure.wd
and configure.usb scripts (see below).
makefile.in — a template for the main makefile for building and installing the WinDriver
kernel driver modules, using makefile.wd[.kbuild] and makefile.usb[.kbuild].
If you are distributing a 32-bit application/shared object to a target 64-bit platform [A.2] — copy
libwdapi1251_32.so from the WinDriver/lib directory to your distribution package, and rename
the copy to libwdapi1251.so.
Since your hardware-control application/shared object does not have to be matched against the
Linux kernel version number, you may distribute it as a binary object (to protect your code from
unauthorized copying). If you select to distribute your driver's source code, note that under the
license agreement with Jungo you may not distribute the source code of the libwdapi1251.so
shared object, or the WinDriver license string used in your code.
• The configuration script creates a makefile based on the running kernel. You
may select to use another installed kernel source, by executing the script with the
--with-kernel-source=<path> option, where <path> is the full path to
the kernel source directory — e.g., /usr/src/linux.
• If the Linux kernel version is 2.6.26 or higher, the configuration script generates
makefiles that use kbuild to compile the kernel modules. You can force the use of
kbuild on earlier versions of Linux, by executing the configuration script with the
--enable-kbuild flag.
For a full list of the configuration script options, use the --help option:
./configure --help
# make install
The installation is performed using the setup_inst_dir script, which copies the driver
modules to the target's loadable kernel modules directory, and uses the wdreg script [9.3] to
load the driver modules.
4. Change the user and group IDs and give read/write permissions to the device file
/dev/windrvr1251, depending on how you wish to allow users to access hardware
through the device. Due to security reasons, by default the device file is created
with permissions only for the root user. Change the permissions by modifying your
/etc/udev/permissions.d/50-udev.permissions file. For example, add the following line to
provide read and write permissions:
windrvr1251:root:root:0666
Use the wdreg script to dynamically load the WinDriver driver modules on the target after
each boot [9.3]. To automate this, copy wdreg to the target machine, and add the following
line to the target's Linux boot file (for example, /etc/rc.local):
<path to wdreg> windrvr1251
If you decided to distribute the source code of the application/shared object [10.4.1.2], copy the
source code to the target as well.
Remember that you may not distribute the source code of the libwdapi1251.so shared
object or your WinDriver license string as part of the source code distribution [10.4.1.2].
In some cases, the INF file for your specific device is supplied by the operating system. In
other cases, you will need to create an INF file for your device. WinDriver's DriverWizard can
generate a specific INF file for your device. The INF file is used to notify the operating system
that WinDriver now handles the selected device.
For USB devices, you will not be able to access the device with WinDriver (either
from DriverWizard or from the code) without first registering the device to work with
windrvr1251.sys. This is done by installing an INF file for the device. DriverWizard will offer to
automatically generate the INF file for your device.
You can use DriverWizard to generate the INF file on the development machine — as explained
in Section 5.2 of the manual — and then install the INF file on any machine to which you
distribute the driver, as explained in the following sections.
You can use the wdreg utility with the install command to automatically install the INF file:
wdreg -inf <path to the INF file> install
(For more information, refer to Section 9.2.1 of the manual.)
On the development PC, you can have the INF file automatically installed when selecting to
generate the INF file with DriverWizard, by checking the Automatically Install the INF file
option in the DriverWizard's INF generation window (refer to Section 5.2).
It is also possible to install the INF file manually, using either of the following methods:
• Windows Found New Hardware Wizard: This wizard is activated when the device is plugged
in or, if the device was already connected, when scanning for hardware changes from the
Device Manager.
• Windows Upgrade Device Driver Wizard: Locate the device in the Device Manager devices
list and select the Update Driver... option from the right-click mouse menu or from the Device
Manager's Action menu.
In all the manual installation methods above you will need to point Windows to the location of the
relevant INF file during the installation.
We recommend using the wdreg utility to install the INF file automatically, instead of installing it
manually.
You can use the wdreg utility with the install command to automatically install the INF
file:
wdreg -inf <path to INF file> install
(For more information, refer to Section 9.2.1 of the manual.)
On the development PC, you can have the INF file automatically installed when selecting to
generate the INF file with DriverWizard, by checking the Automatically Install the INF file
option in the DriverWizard's INF generation window (refer to Section 5.2).
It is also possible to install the INF file manually, using either of the following methods:
• Windows Found New Hardware Wizard: This wizard is activated when the device is
plugged in or, if the device was already connected, when scanning for hardware changes
from the Device Manager.
• Windows Upgrade Device Driver Wizard: Locate the device in the Device Manager
devices list and select the Update Driver... option from the right-click mouse menu or
from the Device Manager's Action menu.
In the manual installation methods above you will need to point Windows to the location of
the relevant INF file during the installation. If the installation wizard offers to install an INF
file other than the one you have generated, select Install one of the other drivers and choose
your specific INF file from the list.
We recommend using the wdreg utility to install the INF file automatically, instead of
installing it manually.
On Windows and Linux you can change the name of the WinDriver kernel module to your
preferred driver name, and then distribute the renamed driver instead of the default kernel module
— windrvr1251.sys/.o/.ko. The following sections explain how to rename the driver for each of
the supported operating systems.
For information on how to use the Debug Monitor to log debug messages from your
renamed driver, refer to Section 7.2.1.1: Running wddebug_gui for a Renamed Driver.
A renamed WinDriver kernel driver can be installed on the same machine as the original
kernel module. You can also install multiple renamed WinDriver drivers on the same machine,
simultaneously.
Try to give your driver a unique name in order to avoid a potential conflict with other
drivers on the target machine on which your driver will be installed.
• When renaming the driver, the CPU architecture (32-/64-bit) of the development
platform and its WinDriver installation, should match the target platform.
• Renaming the signed windrvr1251.sys driver nullifies its signature. In such cases you
can select either to sign your new driver, or to distribute an unsigned driver. For more
information on driver signing and certification, refer to Section 11.3. For guidelines for
signing and certifying your renamed driver, refer to Section 11.3.2.
References to xxx in this section should be replaced with the name of your generated
DriverWizard driver project.
1. Use the DriverWizard utility to generate driver code for your hardware on Windows (refer
to Section 5.2, Step 7), using your preferred driver name (xxx) as the name of the generated
driver project. The generated project directory (xxx) will include an xxx_installation
directory with the following files and directories:
• redist directory:
xxx.sys — Your new driver, which is actually a renamed copy of the windrvr1251.sys
driver. Note: The properties of the generated driver file (such as the file's version,
company name, etc.) are identical to the properties of the original windrvr1251.sys
driver. You can rebuild the driver with new properties using the files from the generated
xxx_installation sys directory, as explained below.
wdreg.exe, wdreg_gui.exe, and difxapi.dll — Copies of the CUI and GUI versions of
the wdreg WinDriver driver installation utility, and the Driver Install Frameworks API
(DIFxAPI) DLL required by this utility [9.2.1], (respectively). These files are copied
from the WinDriver\util directory, to simplify the installation of the renamed driver.
• sys directory: This directory contains files for advanced users, who wish to change the
properties of their driver file. Note: Changing the file's properties requires rebuilding of the
driver module using the Windows Driver Kit (WDK).
To modify the properties of your xxx.sys driver file:
1. Verify that the WDK is installed on your development PC, or elsewhere on its
network, and set the BASEDIR environment variable to point to the WDK installation
directory.
2. Modify the xxx.rc resources file in the generated sys directory in order to set different
driver file properties.
• The selected build OS must match the CPU architecture of your WinDriver
installation. For example, you cannot select the 64-bit win7_x64 OS flag
when using a 32-bit WinDriver installation.
After rebuilding the xxx.sys driver, copy the new driver file to the generated
xxx_installation\redist directory.
2. Verify that your user-mode application calls the WD_DriverName() function [B.1] with
your new driver name before calling any other WinDriver function.
Note that the sample and generated DriverWizard WinDriver applications already include a
call to this function, but with the default driver name (windrvr1251), so all you need to do is
replace the driver name that is passed to the function in the code with your new driver name.
3. Verify that your user-mode driver project is built with the WD_DRIVER_NAME_CHANGE
preprocessor flag (e.g., -DWD_DRIVER_NAME_CHANGE).
Note: The sample and generated DriverWizard WinDriver kernel projects/makefiles already
set this preprocessor flag by default.
4. Install your new driver by following the instructions in Section 10.2 of the manual, using the
modified files from the generated xxx_installation directory instead of the installation files
from the original WinDriver distribution. Note that you can use the generated xxx_install.bat
installation script (see Step 1) to simplify the installation.
References to xxx in this section should be replaced with the name of your generated
DriverWizard driver project.
1. Use the DriverWizard utility to generate driver code for your hardware on Linux (refer to
Section 5.2, Step 7), using your preferred driver name (xxx) as the name of the generated
driver project. The generated project directory (xxx) will include an xxx_installation
directory with the following files and directories:
• redist directory: This directory contains copies of the files from the original
WinDriver/redist installation directory, but with the required modifications for building
your xxx.o/.ko driver instead of windrvr1251.o/.ko.
• lib and include directories: Copies of the library and include directories from the original
WinDriver distribution. These copies are created since the supported Linux WinDriver
kernel driver build method relies on the existence of these directories directly under the
same parent directory as the redist directory.
2. Verify that your user-mode application calls the WD_DriverName() function [B.1] with
your new driver name before calling any other WinDriver function.
Note that the sample and generated DriverWizard WinDriver applications already include a
call to this function, but with the default driver name (windrvr1251), so all you need to do is
replace the driver name that is passed to the function in the code with your new driver name.
3. Verify that your user-mode driver project is built with the WD_DRIVER_NAME_CHANGE
preprocessor flag (-DWD_DRIVER_NAME_CHANGE).
Note: The sample and generated DriverWizard WinDriver kernel projects/makefiles already
set this preprocessor flag by default.
4. Install your new driver by following the instructions in Section 10.4 of the manual, using the
modified files from the generated xxx_installation directory instead of the installation files
from the original WinDriver distribution.
As part of the installation, build your new kernel driver module(s) by following the
instructions in Section 10.4, using the files from your new installation directory.
11.3.1. Overview
Before distributing your driver, you may digitally sign it using Microsoft's Authenticode
mechanism, and/or certify it by submitting it to Microsoft's Windows Certification Program
(HLK/HCK/WLP).
Some Windows operating systems, such as Windows 7, do not require installed drivers to be
digitally signed or certified. Only a popup with a warning will appear
There are, however, advantages to getting your driver digitally signed or fully certified, including
the following:
• Driver installation on systems where installing unsigned drivers has been blocked
64-bit versions of Windows 8 and higher require Kernel-Mode Code Signing (KMCS) of software
that loads in kernel mode. This has the following implications for WinDriver-based drivers:
• Drivers that are installed via an INF file must be distributed together with a signed catalog file
(see details in Section 11.3.2).
During driver development, please configure your Windows OS to temporarily allow the
installation of unsigned drivers.
For more information about digital driver signing and certification, refer to the following
documentation in the Microsoft Development Network (MSDN) library:
• https://msdn.microsoft.com/en-us/windows-drivers/develop/signing_a_driver
Some of the documentation may still use old terminology. For example, references to the
Windows Logo Program (WLP) or to the Windows Hardware Quality Labs (WHQL) or to
the Windows Certification Program or to the Windows Hardware Certification Kit (HCK)
should be replaced with the Windows Hardware Lab Kit (HLK), and references to the
Windows Quality Online Services (Winqual) should be replaced with the Windows Dev
Center Hardware Dashboard Services (the Hardware Dashboard).
To digitally sign and certify a device driver, a Windows Hardware Lab Kit (HLK) package,
which includes the driver and the related hardware, should be submitted to the Windows
Certification Program for testing, using the Windows Dev Center Hardware Dashboard Services
(the Hardware Dashboard).
Jungo's professional services unit provides a complete Windows driver certification service
for Jungo-based drivers. Professional engineers efficiently perform all the tests required
by the Windows Certification Program, relieving customers of the expense and stress of
in-house testing. Jungo prepares an HLK / HCK submission package containing the test
results, and delivers the package to the customer, ready for submission to Microsoft.
For more information, refer to
http://www.jungo.com/st/services/windows_drivers_certification/.
For detailed information regarding Microsoft's Windows Certification Program and the
certification process, refer to the MSDN Windows Hardware Certification page — http://
msdn.microsoft.com/library/windows/hardware/gg463010.aspx — and to the documentation
referenced from that page, including the MSDN Windows Dev Center — Hardware Dashboard
Services page page — http://msdn.microsoft.com/library/windows/hardware/gg463091.
The driver certification and signature procedures — either via Authenticode or the Windows
Certification Program — require the creation of a catalog file for the driver. This file is a sort of
hash, which describes other files. The signed windrvr1251.sys driver is provided with a matching
catalog file — WinDriver\redist\windrvr1251.cat. This file is assigned to the CatalogFile
entry in the windrvr1251.inf file (provided as well in the redist directory). This entry is used
to inform Windows of the driver's signature and the relevant catalog file during the driver's
installation.
When the name, contents, or even the date of the files described in a driver's catalog file is
modified, the catalog file, and consequently the driver signature associated with it, become
invalid. Therefore, if you select to rename the windrvr1251.sys driver [11.2] and/or the related
windrvr1251.inf file, the windrvr1251.cat catalog file and the related driver signature will
become invalid.
In addition, when using WinDriver to develop a driver for your Plug-and-Play device, you
normally also create a device-specific INF file that registers your device to work with the
windrvr1251.sys driver module (or a renamed version of this driver). Since this INF file is
created at your site, for your specific hardware, it is not referenced from the windrvr1251.cat
catalog file and cannot be signed by Jungo a priori.
When renaming windrvr1251.sys and/or creating a device-specific INF file for your device, you
have two alternative options regarding your driver's digital signing:
• Do not digitally sign your driver. If you select this option, remove or comment-out the
reference to the windrvr1251.cat file from the windrvr1251.inf file (or your renamed version
of this file).
• Submit your driver to the Windows Certification Program, or have it Authenticode signed.
Note that while renaming WinDriver\redist\windrvr1251.sys nullifies the driver's digital
signature, the driver is still compliant with the certification requirements of the Windows
Certification Program.
Create a new catalog file for your driver, as explained in the Windows Certification Program
documentation. The new file should reference both windrvr1251.sys (or your renamed
driver) and any INF files used in your driver's installation.
Assign the name of your new catalog file to the CatalogFile entry in your driver's
INF file(s). (You can either change the CatalogFile entry in the windrvr1251.inf file
to refer to your new catalog file, and add a similar entry in your device-specific INF file;
or incorporate both windrvr1251.inf and your device INF file into a single INF file that
contains such a CatalogFile entry).
Note that many WinDriver customers have already successfully digitally signed and certified
their WinDriver-based drivers.
The project or makefile for a 64-bit driver project must include the KERNEL_64BIT
preprocessor definition. In the makefiles, the definition is added using the -D flag:
-DKERNEL_64BIT.
The sample and wizard-generated Linux and Windows GCC makefiles and the Windows
MS Visual Studio projects, in the 64-bit WinDriver toolkit, already include this definition.
To create a 32-bit application for 64-bit Windows or Linux platforms, using the 64-bit version of
WinDriver, do the following:
1. Create a WinDriver application, as outlined in this manual (e.g., by generating code with
DriverWizard, or using one of the WinDriver samples).
2. Build the application with an appropriate 32-bit compiler for your target OS, using the
following configuration:
The sample and wizard-generated Linux and Windows GCC makefiles and the Windows
MS Visual Studio projects, in the 64-bit WinDriver toolkit, already include this definition.
• Link the application with the specific version of the WinDriver-API library/
shared object for 32-bit applications executed on 64-bit platforms —
<WD64>\lib\amd64\x86\wdapi1251.lib on Windows / <WD64>/lib/libwdapi1251_32.so
on Linux.
The sample and wizard-generated project and make files for 32-bit applications in the
64-bit WinDriver toolkit already link to the correct library:
On Windows, the MS Visual Studio project files and Windows GCC makefiles are defined
to link with <WD64>\lib\amd64\x86\wdapi1251.lib.
On Linux, the installation of the 64-bit WinDriver toolkit on the development machine
creates a libwdapi1251.so symbolic link in the /usr/lib directory — which links to
<WD64>/lib/libwdapi1251_32.so — and in the /usr/lib64 directory — which links to
<WD64>/lib/libwdapi1251.so (the 64-bit version of this shared object).
The sample and wizard-generated WinDriver makefiles rely on these symbolic links to
link with the appropriate shared object, depending on whether the code is compiled using a
32-bit or 64-bit compiler.
• When distributing your application to target 64-bit platforms, you need to provide
with it the WinDriver-API DLL/shared object for 32-bit applications executed
on 64-bit platforms — <WD64>\redist\wdapi1251_32.dll on Windows /
<WD64>/lib/libwdapi1251_32.so on Linux. Before distributing this file, rename
the copy of the file in your distribution package by removing the _32 portion. The
installation on the target should copy the renamed DLL/shared object to the relevant
OS directory — \%windir%\sysWOW64 on Windows or /usr/lib on Linux. All other
distribution files are the same as for any other 64-bit WinDriver driver distribution, as
detailed in Chapter 10.
• An application created using the method described in this section will not work on 32-bit
platforms. A WinDriver application for 32-bit platforms needs to be compiled without
the KERNEL_64BIT definition; it needs to be linked with the standard 32-bit version
of the WinDriver-API library/shared object from the 32-bit WinDriver installation
(<WD32>\lib\x86\wdapi1251.lib on Windows / <WD32>/lib/libwdapi1251.so on
Linux); and it should be distributed with the standard 32-bit WinDriver-API DLL/shared
object (<WD32>\redist\wdapi1251.dll on Windows / <WD32>/lib/libwdapi1251.so on
Linux) and any other required 32-bit distribution file, as outlined in Chapter 10.
B.1. WD_DriverName
Purpose
Sets the name of the WinDriver kernel module, which will be used by the calling application.
• The default driver name, which is used if the function is not called, is windrvr1251.
• This function must be called once, and only once, from the beginning of your application,
before calling any other WinDriver function (including WD_Open() / WDU_Init()), as
demonstrated in the sample and generated DriverWizard WinDriver applications, which
include a call to this function with the default driver name — windrvr1251.
• On Windows and Linux, if you select to modify the name of the WinDriver kernel module
(windrvr1251.sys/.o/.ko), as explained in Section 11.2, you must ensure that your application
calls WD_DriverName() with your new driver name.
• In order to use the WD_DriverName() function, your user-mode driver project must be built
with WD_DRIVER_NAME_CHANGE preprocessor flag (e.g.: -DWD_DRIVER_NAME_CHANGE
— for MS Visual Studio, Windows GCC, and GCC).
The sample and generated DriverWizard Windows and Linux WinDriver projects/makefiles
already set this preprocessor flag.
Prototype
const char* DLLCALLCONV WD_DriverName(const char* sName);
Parameters
Description
Name Description
sName The name of the WinDriver kernel module to be used by the
application.
NOTE: The driver name should be indicated without the driver file's
extension. For example, use windrvr1251, not windrvr1251.sys or
windrvr1251.o.
Return Value
Returns the selected driver name on success; returns NULL on failure (e.g., if the function is
called twice from the same application)long.
Remarks
The ability to rename the WinDriver kernel module is supported on Windows and Linux, as
explained in Section 11.2.
On Windows CE, always call the WD_DriverName() function with the default WinDriver
kernel module name — windrvr1251 — or refrain from calling the function altogether.
• Instructions for upgrading code developed with the previous WinDriver USB API, used in
version 5.22 and earlier, to use the improved WDU_xxx API — see Section B.2.2.
If you do not need to upgrade USB driver code developed with an older version of WinDriver,
simply skip this section.
You can implement the three user callback functions specified in the next section:
WDU_ATTACH_CALLBACK [B.3.1], WDU_DETACH_CALLBACK [B.3.2] and
WDU_POWER_CHANGE_CALLBACK [B.3.3] (at the very least WDU_ATTACH_CALLBACK).
These functions are used to notify your application when a relevant system event occurs, such as
the attaching or detaching of a USB device. For best performance, minimal processing should be
done in these functions.
Your application calls WDU_Init() [B.4.1] and provides the criteria according to which the
system identifies a device as relevant or irrelevant. The WDU_Init() function must also pass
pointers to the user callback functions.
Your application then simply waits to receive a notification of an event. Upon receipt of such a
notification, processing continues. Your application may make use of any functions defined in the
high- or low-level APIs below. The high-level functions, provided for your convenience, make
use of the low-level functions, which in turn use IOCTLs to enable communication between the
WinDriver kernel module and your user-mode application.
When exiting, your application calls WDU_Uninit() [B.4.7] to stop listening to devices
matching the given criteria and to unregister the notification callbacks for these devices.
The following figure depicts the calling sequence described above. Each vertical line represents a
function or process. Each horizontal arrow represents a signal or request, drawn from the initiator
to the recipient. Time progresses from top to bottom.
The following piece of meta-code can serve as a framework for your user-mode application's
code:
attach()
{
...
if this is my device
/*
Set the desired alternate setting ;
Signal main() about the attachment of this device
*/
return TRUE;
else
return FALSE;
}
detach()
{
...
signal main() about the detachment of this device
...
}
main()
{
WDU_Init(...);
...
while (...)
{
/* wait for new devices */
...
/* issue transfers */
...
}
...
WDU_Uninit();
}
As a result of this change, you will need to modify your USB applications that were designed to
interface with earlier versions of WinDriver to ensure that they will work with WinDriver v6.X on
all supported platforms and not only on Microsoft Windows.
You will have to reorganize your application's code so that it conforms with the framework
illustrated by the piece of meta-code provided in Section B.2.1.
In addition, the functions that collectively define the USB API have been changed. The new
functions, described in the next few sections, provide an improved interface between user-mode
USB applications and the WinDriver kernel module. Note that the new functions receive their
parameters directly, unlike the old functions, which received their parameters using a structure.
The table below lists the legacy functions in the left column and indicates in the right column
which function or functions replace(s) each of the legacy functions. Use this table to quickly
determine which new functions to use in your new code.
Problem Solution
High Level API
Previous Function New Function
WD_Open() WDU_Init() [B.4.1]
WD_Version()
WD_UsbScanDevice()
WD_UsbDeviceRegister() WDU_SetInterface() [B.4.2]
WD_UsbGetConfiguration() WDU_GetDeviceInfo() [B.4.5]
WD_UsbDeviceUnregister() WDU_Uninit() [B.4.7]
Low Level API
Previous Function New Function
WD_UsbTransfer() WDU_Transfer() [B.4.8.1]
WDU_TransferDefaultPipe() [B.4.8.3]
WDU_TransferBulk() [B.4.8.4]
WDU_TransferIsoch() [B.4.8.5]
WDU_TransferInterrupt() [B.4.8.6]
USB_TRANSFER_HALT option WDU_HaltTransfer() [B.4.8.2]
WD_UsbResetPipe() WDU_ResetPipe() [B.4.10]
WD_UsbResetDevice() WDU_ResetDevice() [B.4.11]
WD_UsbResetDeviceEx()
B.3.1. WDU_ATTACH_CALLBACK
Purpose
WinDriver calls this function when a new device, matching the given criteria, is attached,
provided it is not yet controlled by another driver.
This callback is called once for each matching interface.
Prototype
typedef BOOL (DLLCALLCONV *WDU_ATTACH_CALLBACK)(
WDU_DEVICE_HANDLE hDevice,
WDU_DEVICE *pDeviceInfo,
PVOID pUserData);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
pDeviceInfo Pointer to a USB device information structure [B.5.2.3]; Valid until the
end of the function
pUserData Pointer to user-mode data for the callback, as passed to
WDU_Init() [B.4.1] within the event table parameter
(pEventTable->pUserData)
Return Value
If the WD_ACKNOWLEDGE flag was set in the call to WDU_Init() [B.4.1] (within the
dwOptions parameter), the callback function should check if it wants to control the device, and
if so return TRUE (otherwise — return FALSE).
If the WD_ACKNOWLEDGE flag was not set in the call to WDU_Init(), then the return value of
the callback function is insignificant.
B.3.2. WDU_DETACH_CALLBACK
Purpose
WinDriver calls this function when a controlled device has been detached from the system.
Prototype
typedef void (DLLCALLCONV *WDU_DETACH_CALLBACK)(
WDU_DEVICE_HANDLE hDevice,
PVOID pUserData);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
pUserData Pointer to user-mode data for the callback, as passed to
WDU_Init() [B.4.1] within the event table parameter
(pEventTable->pUserData)
Return Value
None
B.3.3. WDU_POWER_CHANGE_CALLBACK
Purpose
WinDriver calls this function when a controlled device has changed its power settings.
Prototype
typedef BOOL (DLLCALLCONV *WDU_POWER_CHANGE_CALLBACK)(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPowerState,
PVOID pUserData);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwPowerState Number of the power state selected
pUserData Pointer to user-mode data for the callback, as passed to
WDU_Init() [B.4.1] within the event table parameter
(pEventTable->pUserData)
Return Value
Remarks
B.4.1. WDU_Init
Purpose
Starts listening to devices matching input criteria and registers notification callbacks for these
devices.
Prototype
DWORD WDU_Init(
WDU_DRIVER_HANDLE *phDriver,
WDU_MATCH_TABLE *pMatchTables,
DWORD dwNumMatchTables,
WDU_EVENT_TABLE *pEventTable,
const char *sLicense,
DWORD dwOptions);
Parameters
Description
Name Description
phDriver Handle to the registration of events & criteria
pMatchTables Array of match tables [B.5.2.1] defining the devices' criteria
dwNumMatchTables Number of elements in pMatchTables
pEventTable Pointer to an event table structure [B.5.2.2], which holds the
addresses of the user-mode device status change notification callback
functions [B.3] and the data to pass to the callbacks
sLicense WinDriver's license string
dwOptions Can be zero or :
• WD_ACKNOWLEDGE — the user can seize control over the device
when returning value in WDU_ATTACH_CALLBACK [B.3.1]
Return Value
B.4.2. WDU_SetInterface
Purpose
Prototype
DWORD WDU_SetInterface(
WDU_DEVICE_HANDLE hDevice,
DWORD dwInterfaceNum,
DWORD dwAlternateSetting);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwInterfaceNum The interface's number
dwAlternateSetting The desired alternate setting value
Return Value
Remarks
On Windows CE — as opposed to Windows — WDU_SetInterface() attempts to open all
the pipes of the specified alternate setting, even if not all pipes are currently required. The reason
for this is that Windows CE limits the total number of pipes that can be opened simultaneously on
a device, to 16 (see http://msdn.microsoft.com/en-us/library/ms919318.aspx). By opening all the
pipes, the driver ensures that the pipes will be available for use, when needed.
The pipes are opened using the Windows CE USB host controller driver's LPOPEN_PIPE
callback. On some Windows CE devices, the call to this callback fails, causing
WDU_SetInterface() to fail as well. To resolve such problems, upgrade the device's USB
host controller driver.
B.4.3. WDU_GetDeviceAddr
Purpose
Gets the USB address for a given device.
Prototype
DWORD WDU_GetDeviceAddr(
WDU_DEVICE_HANDLE hDevice,
ULONG *pAddress);
Parameters
Description
Name Description
hDevice A unique identifier for a device/interface
pAddress A pointer to the address number returned by the function
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
This function is supported only on Windows and Linux.
B.4.4. WDU_GetDeviceRegistryProperty
Purpose
Gets the specified registry property of a given USB device.
Prototype
DWORD DLLCALLCONV WDU_GetDeviceRegistryProperty(
WDU_DEVICE_HANDLE hDevice,
PVOID pBuffer,
PDWORD pdwSize,
WD_DEVICE_REGISTRY_PROPERTY property);
Parameters
Name Type Input/Output
hDevice WDU_DEVICE_HANDLE Input
pBuffer PVOID Output
pdwSize PDWORD Input/Output
property WD_DEVICE_REGISTRY_PROPERTY Input
Description
Name Description
hDevice A unique identifier of the device/interface
pBuffer Pointer to a user allocated buffer to be filled with the requested registry
property. The function will fill the buffer only if the buffer size, as
indicated in the input value of the pdwSize parameter, is sufficient —
i.e., >= the property's size, as returned via pdwSize.
pBuffer can be set to NULL when using the function only to retrieve
the size of the registry property (see pdwSize).
pdwSize As input, points to a value indicating the size of the user-supplied
buffer (pBuffer); if pBuffer is set to NULL, the input value of this
parameter is ignored.
As output, points to a value indicating the required buffer size for
storing the registry property.
property The ID of the registry property to be retrieved — see the description of
the WD_DEVICE_REGISTRY_PROPERTY enumeration [B.5.1].
Note: String registry properties are in WCHAR format.
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
• When the size of the provided user buffer (pBuffer ) — *pdwSize (input)
— is not sufficient to hold the requested registry property, the function returns
WD_INVALID_PARAMETER.
B.4.5. WDU_GetDeviceInfo
Purpose
Gets configuration information from a device, including all the device descriptors.
NOTE: The caller to this function is responsible for calling WDU_PutDeviceInfo() [B.4.6] in
order to free the *ppDeviceInfo pointer returned by the function.
Prototype
DWORD WDU_GetDeviceInfo(
WDU_DEVICE_HANDLE hDevice,
WDU_DEVICE **ppDeviceInfo);
Parameters
Description
Name Description
hDevice A unique identifier for a device/interface
ppDeviceInfo Pointer to pointer to a USB device information structure [B.5.2.3]
Return Value
B.4.6. WDU_PutDeviceInfo
Purpose
Prototype
void WDU_PutDeviceInfo(WDU_DEVICE *pDeviceInfo);
Parameters
Description
Name Description
pDeviceInfo Pointer to a USB device information structure [B.5.2.3], as returned by
a previous call to WDU_GetDeviceInfo() [B.4.5]
Return Value
None
B.4.7. WDU_Uninit
Purpose
Stops listening to devices matching a given criteria and unregisters the notification callbacks for
these devices.
Prototype
void WDU_Uninit(WDU_DRIVER_HANDLE hDriver);
Parameters
Description
Name Description
hDriver Handle to the registration received from WDU_Init() [B.4.1]
Return Value
None
B.4.8.1. WDU_Transfer
Purpose
Prototype
DWORD WDU_Transfer(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum,
DWORD fRead,
DWORD dwOptions,
PVOID pBuffer,
DWORD dwBufferSize,
PDWORD pdwBytesTransferred,
PBYTE pSetupPacket,
DWORD dwTimeout);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface received from
WDU_Init() [B.4.1]
dwPipeNum The number of the pipe through which the data is transferred
fRead TRUE for read, FALSE for write
dwOptions A bit-mask of USB transfer options, which can consist of a
combination of any of the following flags:
• USB_ISOCH_NOASAP — Instructs the lower USB stack driver
(usbd.sys) to use a preset frame number (instead of the next available
frame) for an isochronous data transfer.
It is recommended that you use this flag for isochronous write
(OUT) transfers, and if you notice unused frames during transfers on
low-speed or full-speed USB 1.1 devices.
This flag is available only for Windows.
• USB_ISOCH_FULL_PACKETS_ONLY — Prevents transfers of less
than the packet size on isochronous pipes.
• USB_BULK_INT_URB_SIZE_OVERRIDE_128K — Limits the
size of the USB Request Block (URB) to 128KB.
This flag is available only for Windows.
• USB_ISOCH_RESET — Resets the isochronous pipe before the
data transfer. It also resets the pipe after minor errors, consequently
allowing to transfer to continue.
pBuffer Address of the data buffer
dwBufferSize Number of bytes to transfer. The buffer size is not limited to the
device's maximum packet size; therefore, you can use larger buffers
by setting the buffer size to a multiple of the maximum packet size.
Use large buffers to reduce the number of context switches and thereby
improve performance.
pdwBytesTransferred Number of bytes actually transferred
pSetupPacket An 8-byte packet to transfer to control pipes
dwTimeout Maximum time, in milliseconds (ms), to complete a transfer.
A value of zero indicates no timeout (infinite wait).
Return Value
Remarks
The resolution of the timeout (the dwTimeout parameter) is according to the operating system
scheduler's time slot. For example, in Windows the timeout's resolution is 10 milliseconds (ms).
B.4.8.2. WDU_HaltTransfer
Purpose
Halts the transfer on the specified pipe (only one simultaneous transfer per pipe is allowed by
WinDriver).
Prototype
DWORD WDU_HaltTransfer(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwPipeNum The number of the pipe
Return Value
B.4.8.3. WDU_TransferDefaultPipe
Purpose
Transfers data to or from a device through the default control pipe (pipe 0).
Prototype
DWORD WDU_TransferDefaultPipe(
WDU_DEVICE_HANDLE hDevice,
DWORD fRead,
DWORD dwOptions,
PVOID pBuffer,
DWORD dwBufferSize,
PDWORD pdwBytesTransferred,
PBYTE pSetupPacket,
DWORD dwTimeout);
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.8.4. WDU_TransferBulk
Purpose
Performs bulk data transfer to or from a device.
Prototype
DWORD WDU_TransferBulk(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum,
DWORD fRead,
DWORD dwOptions,
PVOID pBuffer,
DWORD dwBufferSize,
PDWORD pdwBytesTransferred,
DWORD dwTimeout);
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.8.5. WDU_TransferIsoch
Purpose
Performs isochronous data transfer to or from a device.
Prototype
DWORD WDU_TransferIsoch(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum,
DWORD fRead,
DWORD dwOptions,
PVOID pBuffer,
DWORD dwBufferSize,
PDWORD pdwBytesTransferred,
DWORD dwTimeout);
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.8.6. WDU_TransferInterrupt
Purpose
Performs interrupt data transfer to or from a device.
Prototype
DWORD WDU_TransferInterrupt(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum,
DWORD fRead,
DWORD dwOptions,
PVOID pBuffer,
DWORD dwBufferSize,
PDWORD pdwBytesTransferred,
DWORD dwTimeout);
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
The streaming APIs are currently supported on Windows and Windows CE.
B.4.9.1. WDU_StreamOpen
Purpose
Prototype
DWORD DLLCALLCONV WDU_StreamOpen(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum,
DWORD dwBufferSize,
DWORD dwRxSize,
BOOL fBlocking,
DWORD dwOptions,
DWORD dwRxTxTimeout,
WDU_STREAM_HANDLE *phStream);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwPipeNum The number of the pipe for which to open the stream
dwBufferSize The size, in bytes, of the stream's data buffer
dwRxSize The size, in bytes, of the data blocks that the stream reads from the
device. This parameter is relevant only for read streams, and must
not exceed the value of the dwBufferSize parameter. Note: When
setting the USB_STREAM_MAX_TRANSFER_SIZE_OVERWRITE
dwOptions flag, this is also the maximum transfer size.
fBlocking • TRUE for a blocking stream, which performs blocked I/O;
• FALSE for a non-blocking stream, which performs non-blocking I/O.
For additional information, refer to Section 8.3.3.1.
dwOptions A bit-mask of USB transfer options, which can consist of a
combination of any of the following flags:
• USB_ISOCH_NOASAP — Instructs the lower USB stack driver
(usbd.sys) to use a preset frame number (instead of the next available
frame) for an isochronous data transfer.
It is recommended that you use this flag for isochronous write
(OUT) transfers, and if you notice unused frames during transfers on
low-speed or full-speed USB 1.1 devices.
This flag is available only for Windows.
• USB_ISOCH_FULL_PACKETS_ONLY — Prevents transfers of less
than the packet size on isochronous pipes.
• USB_BULK_INT_URB_SIZE_OVERRIDE_128K — Limits the
size of the USB Request Block (URB) to 128KB.
This flag is available only for Windows.
• USB_STREAM_OVERWRITE_BUFFER_WHEN_FULL — When
there is not enough free space in a read stream's data buffer to
complete the transfer, overwrite old data in the buffer. This flag is
applicable only to read streams.
• USB_STREAM_MAX_TRANSFER_SIZE_OVERRIDE — Overrides
the default maximum transfer size with the dwRxSize transfer size,
on Windows CE. Note that setting a large dwRxSize value when
using this flag, may cause the transfers to fail due to host controller
limitations.
This flag is applicable only to read streams on Windows CE.
dwRxTxTimeout Maximum time, in milliseconds (ms), for the completion of a data
transfer between the stream and the device.
A value of zero indicates no timeout (infinite wait).
phStream Pointer to a unique identifier for the stream, to be returned by the
function and passed to the other WDU_StreamXXX() functions
Return Value
B.4.9.2. WDU_StreamStart
Purpose
Starts a stream, i.e., starts transfers between the stream and the device.
Data will be transferred according to the stream's direction — read/write.
Prototype
DWORD DLLCALLCONV WDU_StreamStart(
WDU_STREAM_HANDLE hStream);
Parameters
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
Return Value
B.4.9.3. WDU_StreamRead
Purpose
Reads data from a read stream to the application.
For both blocking and non-blocking transfers, the function returns the amount of bytes that were
actually read from the stream within the pdwBytesRead parameter.
Prototype
DWORD DLLCALLCONV WDU_StreamRead(
HANDLE hStream,
PVOID pBuffer,
DWORD bytes,
DWORD *pdwBytesRead);
Parameters
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
pBuffer Pointer to a data buffer to be filled with the data read from the stream
bytes Number of bytes to read from the stream
pdwBytesRead Pointer to a value indicating the number of bytes actually read from the
stream
Return Value
B.4.9.4. WDU_StreamWrite
Purpose
For a non-blocking stream (fBlocking=FALSE), the function writes as much data as currently
possible to the stream's data buffer, and returns immediately.
For both blocking and non-blocking transfers, the function returns the amount of bytes that were
actually written to the stream within the pdwBytesWritten parameter.
Prototype
DWORD DLLCALLCONV WDU_StreamWrite(
HANDLE hStream,
const PVOID pBuffer,
DWORD bytes,
DWORD *pdwBytesWritten);
Parameters
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
pBuffer Pointer to a data buffer containing the data to write to the stream
bytes Number of bytes to write to the stream
pdwBytesWritten Pointer to a value indicating the number of bytes actually written to the
stream
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or WD_OPERATION_FAILED on failure.
In case of failure, call WDU_StreamGetStatus() [B.4.9.6] to get the current stream status.
B.4.9.5. WDU_StreamFlush
Purpose
Flushes a write stream, i.e., writes the entire contents of the stream's data buffer to the device.
The function blocks until the completion of all pending I/O on the stream.
This function can be called for both blocking and non-blocking streams.
Prototype
DWORD DLLCALLCONV WDU_StreamFlush(
WDU_STREAM_HANDLE hStream);
Parameters
Name Type Input/Output
hStream WDU_STREAM_HANDLE Input
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.9.6. WDU_StreamGetStatus
Purpose
Prototype
DWORD DLLCALLCONV WDU_StreamGetStatus(
WDU_STREAM_HANDLE hStream,
BOOL *pfIsRunning,
DWORD *pdwLastError,
DWORD *pdwBytesInBuffer);
Parameters
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
pfIsRunning Pointer to a value indicating the stream's current state:
• TRUE — the stream is currently running
• FALSE — the stream is currently stopped
pdwLastError Pointer to the last error associated with the stream.
Note: Calling the function also resets the stream's last error.
pdwBytesInBuffer Pointer to the current bytes count in the stream's data buffer
Return Value
B.4.9.7. WDU_StreamStop
Purpose
Stops an active stream, i.e., stops transfers between the stream and the device.
In the case of a write stream, the function flushes the stream — i.e., writes its contents to the
device — before stopping it.
Prototype
DWORD DLLCALLCONV WDU_StreamStop(WDU_STREAM_HANDLE hStream);
Parameters
Name Type Input/Output
hStream WDU_STREAM_HANDLE Input
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.9.8. WDU_StreamClose
Purpose
Closes an open stream.
The function stops the stream, including flushing its data to the device (in the case of a write
stream), before closing it.
Prototype
DWORD DLLCALLCONV WDU_StreamClose(WDU_STREAM_HANDLE hStream);
Parameters
Name Type Input/Output
hStream WDU_STREAM_HANDLE Input
Description
Name Description
hStream A unique identifier for the stream, as returned by
WDU_StreamOpen()
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.4.10. WDU_ResetPipe
Purpose
Resets a pipe by clearing both the halt condition on the host side of the pipe and the stall
condition on the endpoint. This function is applicable for all pipes except the control pipe (pipe
0).
Prototype
DWORD WDU_ResetPipe(
WDU_DEVICE_HANDLE hDevice,
DWORD dwPipeNum);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwPipeNum The pipe's number
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
This function should be used if a pipe is halted, in order to clear the halt.
B.4.11. WDU_ResetDevice
Purpose
Resets a device.
Prototype
DWORD WDU_ResetDevice(
WDU_DEVICE_HANDLE hDevice,
DWORD dwOptions);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface.
dwOptions Can be either zero or:
• WD_USB_HARD_RESET — reset the device even if it is not disabled.
After using this option it is advised to set the interface device using
WDU_SetInterface() [B.4.2].
• WD_USB_CYCLE_PORT — simulate unplugging and replugging of
the device, prompting the operating system to re-enumerate the device
without resetting it.
This option is supported only on Windows 7 and higher.
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
• WDU_ResetDevice() is supported only on Windows and Windows CE, beginning with
Windows CE 5.0.
The WD_USB_CYCLE_PORT option is supported on Windows 7 and higher.
• The function issues a request from the Windows USB driver to reset a hub port, provided the
Windows USB driver supports this feature.
B.4.12. WDU_SelectiveSuspend
Purpose
Submits a request to suspend a given device (selective suspend), or cancels a previous suspend
request.
Prototype
DWORD DLLCALLCONV WDU_SelectiveSuspend(
WDU_DEVICE_HANDLE hDevice,
DWORD dwOptions);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface.
dwOptions Can be set to either of the following
WDU_SELECTIVE_SUSPEND_OPTIONS values:
• WDU_SELECTIVE_SUSPEND_SUBMIT — submit a request to
suspend the device.
• WDU_SELECTIVE_SUSPEND_CANCEL — cancel a previous
request to suspend the device.
Return Value
Remarks
B.4.13. WDU_Wakeup
Purpose
Prototype
DWORD WDU_Wakeup(
WDU_DEVICE_HANDLE hDevice,
DWORD dwOptions);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
dwOptions Can be either:
• WDU_WAKEUP_ENABLE — enable wakeup
OR:
• WDU_WAKEUP_DISABLE — disable wakeup
Return Value
B.4.14. WDU_GetLangIDs
Purpose
Reads a list of supported language IDs and/or the number of supported language IDs from a
device.
Prototype
DWORD DLLCALLCONV WDU_GetLangIDs(
WDU_DEVICE_HANDLE hDevice,
PBYTE pbNumSupportedLangIDs,
WDU_LANGID *pLangIDs,
BYTE bNumLangIDs);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
pbNumSupportedLangIDs Parameter to receive number of supported language IDs
pLangIDs Array of language IDs. If bNumLangIDs is not zero the function
will fill this array with the supported language IDs for the device.
bNumLangIDs Number of IDs in the pLangIDs array
Return Value
Remarks
• If dwNumLangIDs is zero the function will return only the number of supported language IDs
(in pbNumSupportedLangIDs) but will not update the language IDs array (pLangIDs)
with the actual IDs. For this usage pLangIDs can be NULL (since it is not referenced) but
pbNumSupportedLangIDs must not be NULL.
• pbNumSupportedLangIDs can be NULL if the user only wants to receive the list of
supported language IDs and not the number of supported IDs.
In this case bNumLangIDs cannot be zero and pLangIDs cannot be NULL.
• If the device does not support any language IDs the function will return success. The caller
should therefore check the value of *pbNumSupportedLangIDs after the function returns.
• If the size of the pLangIDs array (bNumLangIDs ) is smaller than the number of IDs
supported by the device (*pbNumSupportedLangIDs ), the function will read and return
only the first bNumLangIDs supported language IDs.
B.4.15. WDU_GetStringDesc
Purpose
Prototype
DWORD DLLCALLCONV WDU_GetStringDesc(
WDU_DEVICE_HANDLE hDevice,
BYTE bStrIndex,
PBYTE pbBuf,
DWORD dwBufSize,
WDU_LANGID langID,
PDWORD pdwDescSize);
Parameters
Description
Name Description
hDevice A unique identifier for the device/interface
bStrIndex The index of the string descriptor to read
pbBuf Pointer to a buffer to be filled with the string descriptor
dwBufSize The size of the pbBuf buffer, in bytes
langID The language ID to be used in the get string descriptor request. If
this parameter is 0, the request will use the first supported language ID
returned by the device.
pdwDescSize An optional DWORD pointer to be filled with the size of the string
descriptor read from the device.
If NULL, the size of the string descriptor will not be returned.
Return Value
Remarks
If the size of the pbBuf buffer is smaller than the size of the string descriptor
(dwBufSize*pdwDescSize ), the returned descriptor will be truncated to the provided buffer
size (dwBufSize ).
B.5.1. WD_DEVICE_REGISTRY_PROPERTY
Enumeration
Enumeration of device registry property identifiers.
String properties are returned in NULL-terminated WCHAR array format.
For more information regarding the properties described in this enumaration, refer to the
description of the Windows IoGetDeviceProperty() function's DeviceProperty
parameter in the Microsoft Development Network (MSDN) documentation.
(*) For all field members, if value is set to zero — match all.
B.6.2. WD_Open()
Purpose
Opens a handle to access the WinDriver kernel module.
The handle is used by all WinDriver APIs, and therefore must be called before any other
WinDriver API is called.
Prototype
HANDLE WD_Open(void);
Return Value
The handle to the WinDriver kernel module.
If device could not be opened, returns INVALID_HANDLE_VALUE.
Remarks
If you are a registered user, please refer to the documentation of WD_License() [B.6.9] for an
example of how to register your WinDriver license.
Example
HANDLE hWD;
hWD = WD_Open();
if (hWD == INVALID_HANDLE_VALUE)
{
printf("Cannot open WinDriver device\n");
}
B.6.3. WD_Version()
Purpose
Returns the version number of the WinDriver kernel module currently running.
Prototype
DWORD WD_Version(
HANDLE hWD,
WD_VERSION *pVer);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pVer Pointer to a WinDriver version information structure:
• dwVer The version number
• cVer Version information string.
The version string's size is limited to 128 characters (including the
NULL terminator character).
Return Value
Example
WD_VERSION ver;
BZERO(ver);
WD_Version(hWD, &ver);
printf("%s\n", ver.cVer);
if (ver.dwVer < WD_VER)
{
printf("Error - incorrect WinDriver version\n");
}
B.6.4. WD_Close()
Purpose
Closes the access to the WinDriver kernel module.
Prototype
void WD_Close(HANDLE hWD);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
Return Value
None
Remarks
This function must be called when you finish using WinDriver kernel module.
Example
WD_Close(hWD);
B.6.5. WD_Debug()
Purpose
Prototype
DWORD WD_Debug(
HANDLE hWD,
WD_DEBUG *pDebug);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pDebug Pointer to a debug information structure:
• dwCmd Debug command: Set filter, Clear buffer, etc.
For more details please refer to DEBUG_COMMAND in windrvr.h.
• dwLevel Used for dwCmd=DEBUG_SET_FILTER. Sets the debugging level
to collect: Error, Warning, Info, Trace.
For more details please refer to DEBUG_LEVEL in windrvr.h.
• dwSection Used for dwCmd=DEBUG_SET_FILTER. Sets the sections to
collect: I/O, Memory, Interrupt, etc. Use S_ALL for all.
For more details please refer to DEBUG_SECTION in windrvr.h.
• dwLevelMessageBox Used for dwCmd=DEBUG_SET_FILTER. Sets the debugging level
to print in a message box.
For more details please refer to DEBUG_LEVEL in windrvr.h.
• dwBufferSize Used for dwCmd=DEBUG_SET_BUFFER. The size of buffer in the
kernel.
Return Value
Example
WD_DEBUG dbg;
BZERO(dbg);
dbg.dwCmd = DEBUG_SET_FILTER;
dbg.dwLevel = D_ERROR;
dbg.dwSection = S_ALL;
dbg.dwLevelMessageBox = D_ERROR;
WD_Debug(hWD, &dbg);
B.6.6. WD_DebugAdd()
Purpose
Sends debug messages to the debug log. Used by the driver code.
Prototype
DWORD WD_DebugAdd(
HANDLE hWD,
WD_DEBUG_ADD *pData);
Parameters
Name Type Input/Output
hWD HANDLE Input
pData WD_DEBUG_ADD*
• dwLevel DWORD Input
• dwSection DWORD Input
• pcBuffer CHAR[256] Input
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pData Pointer to an additional debug information structure:
• dwLevel Assigns the level in the Debug Monitor, in which the data will be
declared.
If dwLevel is zero, D_ERROR will be declared.
For more details please refer to DEBUG_LEVEL in windrvr.h.
• dwSection Assigns the section in the Debug Monitor, in which the data will be
declared.
If dwSection is zero, S_MISC section will be declared.
For more details please refer to DEBUG_SECTION in windrvr.h.
• pcBuffer The string to copy into the message log.
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Example
WD_DEBUG_ADD add;
BZERO(add);
add.dwLevel = D_WARN;
add.dwSection = S_MISC;
sprintf(add.pcBuffer, "This message will be displayed in "
"the Debug Monitor\n");
WD_DebugAdd(hWD, &add);
B.6.7. WD_DebugDump()
Purpose
Prototype
DWORD WD_DebugDump(
HANDLE hWD,
WD_DEBUG_DUMP *pDebugDump);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pDebugDump Pointer to a debug dump information structure:
• pcBuffer Buffer to receive debug messages
dwSize Size of buffer in bytes
Return Value
Example
char buffer[1024];
WD_DEBUG_DUMP dump;
dump.pcBuffer=buffer;
dump.dwSize = sizeof(buffer);
WD_DebugDump(hWD, &dump);
B.6.8. WD_Sleep()
Purpose
Delays execution for a specific duration of time.
Prototype
DWORD WD_Sleep(
HANDLE hWD,
WD_SLEEP *pSleep);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pSleep Pointer to a sleep information structure
• dwMicroSeconds Sleep time in microseconds — 1/1,000,000 of a second
• dwOptions A bit-mask, which can be set to either of the following values:
• Zero (0) — Delay execution by consuming CPU cycles
(busy sleep); this is the default.
• SLEEP_NON_BUSY — Delay execution without consuming CPU
resources (non-busy sleep).
Note: The accuracy of non-busy sleep is machine-dependent and
cannot be guaranteed for short sleep intervals (< 1 millisecond).
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
Example usage: to access slow response hardware.
Example
WD_Sleep slp;
BZERO(slp);
slp.dwMicroSeconds = 200;
WD_Sleep(hWD, &slp);
B.6.9. WD_License()
Purpose
Transfers the license string to the WinDriver kernel module.
When using the WDU USB APIs [B.2] your WinDriver license registration is done via the
call to WDU_Init() [B.4.1], so you do not need to call WD_License() directly from your
code.
Prototype
DWORD WD_License(
HANDLE hWD,
WD_LICENSE *pLicense);
Parameters
Description
Name Description
hWD Handle to WinDriver's kernel-mode driver as received from
WD_Open() [B.6.2]
pLicense Pointer to a WinDriver license information structure:
• cLicense A buffer to contain the license string that is to be transferred to the
WinDriver kernel module.
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
Remarks
When using a registered version, this function must be called before any other WinDriver API
call, apart from WD_Open() [B.6.2], in order to register the license from the code.
Example
hWD = WD_Open();
if (hWD!=INVALID_HANDLE_VALUE)
{
BZERO(lic);
/* Replace the following string with your license string: */
strcpy(lic.cLicense, "12345abcde12345.CompanyName");
dwStatus = WD_License(hWD, &lic);
if (dwStatus != WD_STATUS_SUCCESS)
{
WD_Close(hWD);
hWD = INVALID_HANDLE_VALUE;
}
}
return hWD;
}
B.7.1. Stat2Str
Purpose
Retrieves the status string that corresponds to a status code.
Prototype
const char *Stat2Str(DWORD dwStatus);
Parameters
Description
Name Description
• dwStatus A numeric status code
Return Value
Returns the verbal status description (string) that corresponds to the specified numeric status code.
Remarks
See Section B.8 for a complete list of status codes and strings.
B.7.2. get_os_type
Purpose
Retrieves the type of the operating system.
Prototype
OS_TYPE get_os_type(void);
Return Value
Returns the type of the operating system.
If the operating system type is not detected, returns OS_CAN_NOT_DETECT.
B.7.3. ThreadStart
Purpose
Creates a thread.
Prototype
DWORD ThreadStart(
HANDLE *phThread,
HANDLER_FUNC pFunc,
void *pData);
Parameters
Description
Name Description
phThread Returns the handle to the created thread
pFunc Starting address of the code that the new thread is to execute. (The
handler's prototype — HANDLER_FUNC — is defined in utils.h.)
pData Pointer to the data to be passed to the new thread
Return Value
B.7.4. ThreadWait
Purpose
Prototype
void ThreadWait(HANDLE hThread);
Parameters
Description
Name Description
hThread The handle to the thread whose completion is awaited
Return Value
None
B.7.5. OsEventCreate
Purpose
Prototype
DWORD OsEventCreate(HANDLE *phOsEvent);
Parameters
Description
Name Description
phOsEvent The pointer to a variable that receives a handle to the newly created
event object
Return Value
B.7.6. OsEventClose
Purpose
Prototype
void OsEventClose(HANDLE hOsEvent);
Parameters
Description
Name Description
hOsEvent The handle to the event object to be closed
Return Value
None
B.7.7. OsEventWait
Purpose
Waits until a specified event object is in the signaled state or the time-out interval elapses.
Prototype
DWORD OsEventWait(
HANDLE hOsEvent,
DWORD dwSecTimeout);
Parameters
Description
Name Description
hOsEvent The handle to the event object
dwSecTimeout Time-out interval of the event, in seconds.
For an infinite wait, set the timeout to INFINITE.
Return Value
B.7.8. OsEventSignal
Purpose
Prototype
DWORD OsEventSignal(HANDLE hOsEvent);
Parameters
Description
Name Description
hOsEvent The handle to the event object
Return Value
B.7.9. OsEventReset
Purpose
Prototype
DWORD OsEventReset(HANDLE hOsEvent);
Parameters
Description
Name Description
hOsEvent The handle to the event object
Return Value
B.7.10. OsMutexCreate
Purpose
Prototype
DWORD OsMutexCreate(HANDLE *phOsMutex);
Parameters
Description
Name Description
phOsMutex The pointer to a variable that receives a handle to the newly created
mutex object
Return Value
B.7.11. OsMutexClose
Purpose
Prototype
void OsMutexClose(HANDLE hOsMutex);
Parameters
Description
Name Description
hOsMutex The handle to the mutex object to be closed
Return Value
None
B.7.12. OsMutexLock
Purpose
Prototype
DWORD OsMutexLock(HANDLE hOsMutex);
Parameters
Description
Name Description
hOsMutex The handle to the mutex object to be locked
Return Value
B.7.13. OsMutexUnlock
Purpose
Prototype
DWORD OsMutexUnlock(HANDLE hOsMutex);
Parameters
Description
Name Description
hOsMutex The handle to the mutex object to be unlocked
Return Value
B.7.14. PrintDbgMessage
Purpose
Prototype
void PrintDbgMessage(
DWORD dwLevel,
DWORD dwSection,
const char *format
[, argument]...);
Parameters
Description
Name Description
dwLevel Assigns the level in the Debug Monitor, in which the data will be
declared. If zero, D_ERROR will be declared.
For more details please refer to DEBUG_LEVEL in windrvr.h.
dwSection Assigns the section in the Debug Monitor, in which the data will be
declared. If zero, S_MISC will be declared.
For more details please refer to DEBUG_SECTION in windrvr.h.
format Format-control string
argument Optional arguments, limited to 256 bytes
Return Value
None
B.7.15. WD_LogStart
Purpose
Prototype
DWORD WD_LogStart(
const char *sFileName,
const char *sMode);
Parameters
Description
Name Description
sFileName Name of log file to be opened
sMode Type of access permitted.
For example, NULL or w opens an empty file for writing, and if the
given file exists, its contents are destroyed;
a opens a file for writing at the end of the file (i.e., append).
Return Value
Remarks
Once a log file is opened, all API calls are logged in this file.
You may add your own printouts to the log file by calling WD_LogAdd() [B.7.17].
B.7.16. WD_LogStop
Purpose
Closes a log file.
Prototype
VOID WD_LogStop(void);
Return Value
None
B.7.17. WD_LogAdd
Purpose
Adds user printouts into log file.
Prototype
VOID DLLCALLCONV WD_LogAdd(
const char *sFormat
[, argument ]...);
Parameters
Description
Name Description
sFormat Format-control string
argument Optional format arguments
Return Value
Returns WD_STATUS_SUCCESS (0) on success, or an appropriate error code otherwise [B.8].
B.8.1. Introduction
Most of the WinDriver functions return a status code, where zero (WD_STATUS_SUCCESS)
means success and a non-zero value means failure.
The Stat2Str() functions can be used to retrieve the status description string for a given status
code. The status codes and their descriptive strings are listed below.
• Technical documents
• FAQs
• Samples
• When using DriverWizard, a dialogue box with a message stating that an evaluation version is
being run appears on every interaction with the hardware.
• DriverWizard [5]:
• WinDriver will function for only 30 days after the original installation.
• The WinDriver CE Kernel (windrvr1251.dll) will operate for no more than 60 minutes at a
time.
• DriverWizard [5]:
• WinDriver's kernel module will work for no more than 60 minutes at a time. To continue
working, the WinDriver kernel module must be reloaded (unload and load the module) using
the following commands:
To unload —
# /sbin/modprobe -r windrvr1251
To load —
# <path to wdreg> windrvr1251
Feel free to contact us with any question you may have. For full contact information, visit our
contact web page: http://www.jungo.com/st/company/contact-us/.
The most updated WinDriver user manuals can be found on Jungo's site at
http://www.jungo.com/st/support/windriver/.
Version History
If you wish to view WinDriver version history, refer to the WinDriver release notes, available
online at http://www.jungo.com/st/support/windriver/wdver/. The release notes include a list of
the new features, enhancements and fixes that have been added in each WinDriver version.
Technical Documents