Jungo WinDriver  
Official Documentation
Chapter 7: Developing a Driver

This chapter takes you through the WinDriver driver development cycle.

7.1. Using DriverWizard to Build a Device Driver

You can use DriverWizard to diagnose your device and verify that it operates as expected, as well as to generate skeletal code for your device in C, C#, Visual Basic (USB Only), Java and Python. For more information about DriverWizard, refer to Chapter 6: Using DriverWizard.

⚠ Attention

For devices based on the Altera Qsys, Avalon-MM designs, Xilinx BMD, XDMA, QDMA designs, you can use DriverWizard to generate customized device-specific code, which utilizes the enhanced-support sample APIs. For additional information, refer to Chapter 9: Enhanced Support for Specific Chipsets. This is the most recommended way to develop a driver using WinDriver as it saves you the most time and hassle.

Use any C/C#.NET/Python/Java compiler/interpreter 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, CMake, GNU Make/Eclipse (for Java projects).

That is all you need to do in order to create your user-mode driver. If you discover that better performance is needed, refer to Chapter 11: Improving PCI Performance.

To learn how to perform operations that DriverWizard cannot automate, refer to Chapter 10: PCI Advanced Features.

7.2. Using a code sample to Build a Device Driver

If you are using an enhanced-support PCI device (PLX 6466, 9030, 9050, 9052, 9054, 9056, 9080 and 9656; Altera Qsys, Avalon-MM designs; Xilinx BMD, XDMA, QDMA designs), you may want to use the related WinDriver sample as the basis for your development instead of generating code with DriverWizard.

This method is relevant if you are unable to get DriverWizard to work on your platform or if it is not available for your platform and you wish to quickly start developing.

These samples can be found in ´WinDriver/samples/c´. These directories include both the source code and project files to compile them, and also a precompiled version of the sample source code.

⚠ Attention

Note that after your evaluation period has expired the precompiled binaries of the sample will not work, and you will have to recompile them with your new license key.

7.3. Writing the Device Driver Without DriverWizard

There may be times when you choose to write your driver directly, without using DriverWizard.

In such cases, either follow the steps outlined in this section to create a new driver project, or select a WinDriver sample that most closely resembles your target driver and modify it to suit your specific requirements.

This method is recommended only for expert users that are already familiar with the WinDriver API and the required compilation flags needed in order to compile WinDriver.

7.3.1. Include the Required WinDriver Files

Firstly, include the relevant WinDriver header files in your driver project. All header files are found under the WinDriver/include or WinDriver/samples/c/shared (for C projects) directory. All WinDriver projects require the windrvr.h header file.

When using the WDC_xxx API / WDU_xxx API , include the wdc_lib.h / wdu_lib.h and wdc_defs.h header files (these files already include 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/c/shared directory, which provide convenient diagnostics functions.)

Then include the relevant header files from your source code. For example, to use API from the windrvr.h header file, add the following line to the code:

#include "windrvr.h"

Afterwards, link your code with the WDAPI library (Windows) / shared object (Linux):

  • For Windows: WinDriver\lib\amd64\wdapi1620.lib, for compiling 64-bit binaries for x64 platforms, or WinDriver\lib\amd64\x86\wdapi1620_32.lib for compiling 32-bit binaries for x64 platforms or WinDriver\lib\arm64\wdapi1620_arm64.lib for compiling 64-bit binaries for ARM64 platforms.
  • For Linux: From the WinDriver/lib directory — libwdapi1620.so (for 64-bit binaries for x64 platforms) or libwdapi1620_32.so (for 32-bit applications targeted at 64-bit platforms).
  • For MacOS: From the WinDriver/lib directory — libwdapi1620.dylib

(note that WinDriver for MacOS currently doesn't support 32 bit applications on 64-bit platforms).

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/framework/shared object, you will need to distribute this binary with your driver.

  • For Windows, get wdapi1620.dll / wdapi1620_32.dll (for 32-bit applications targeted at 64-bit platforms) / wdapi1620_ARM64.dll (for 64-bit applications targeted at ARM64 platforms) from the WinDriver/redist directory.
  • For Linux, get libwdapi1620.so / libwdapi1620_32.so (for 32-bit applications targeted at 64-bit platforms) from the WinDriver/lib directory.
  • For MacOS, get libwdapi1620.dylib from the WinDriver/lib directory.

ℹ️ Note

WinDriver for MacOS currently doesn't support 32 bit applications on 64-bit platforms.

Add any other WinDriver source files that implement API that you which to use in your code (e.g. files from the WinDriver/samples/c/shared directory.)

7.3.2. Write Your Code (PCI/ISA)

This section outlines the calling sequence when using the WDC_xxx API:

  • Call WDC_DriverOpen() to open a handle to WinDriver and the WDC library, compare the version of the loaded driver with that of your driver source files, and register your WinDriver license (for registered users).
    • For PCI/PCI Express devices, call WDC_PciScanDevices() to scan the PCI bus and locate your device.
    • For PCI/PCI Express devices, call WDC_PciGetDeviceInfo() to retrieve the resources information for your selected device.
    • For ISA devices, define the resources yourself within a WD_CARD structure.
  • Call WDC_PciDeviceOpen() / WDC_IsaDeviceOpen() (depending on your device), and pass to the function the device's resources information. These functions return a handle to the device, which you can later use to communicate with the device using the WDC_xxx API.
  • Communicate with the device using the WDC_xxx API.
  • When you are done:

7.3.3. Write Your Code (USB)

This section outlines the calling sequence when using the WDU_xxx / WDC_xxx API:

  • Call WDC_DriverOpen() to open a handle to WinDriver and the WDC library, compare the version of the loaded driver with that of your driver source files, and register your WinDriver license (for registered users).
  • Call WDU_Init() at the beginning of your program to initialize WinDriver for your USB device, and wait for the device-attach callback. The relevant device information will be provided in the attach callback.
  • Communicate with the device using the WDU_xxx API.
    • Once the attach callback is received, you can start using one of the WDU_Transfer() functions family to send and receive data.
  • When you are done:

7.3.4. Configure and Build Your Code

After including the required files and writing your code, make sure that the required build flags and environment variables are set, then build your code.

⚠ Attention

When developing a driver for a 64-bit platform, 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 and Linux you can define the WD_BASEDIR environment variable globally: for Windows — refer to the Windows WD_BASEDIR note in 3.2.1. Windows WinDriver Installation Instructions; for Linux - refer to 3.2.2. Linux WinDriver Installation Instructions.

⚠ Attention

>If you have renamed your driver make sure you've added -DWD_DRIVER_NAME_CHANGE to your makefile (More information on Driver Renaming is available on Chapter 17: Driver Installation — Advanced Issues).

7.4. Upgrading a Driver

This section is meant for users that already have code written using previous versions of WinDriver and wish to upgrade it to link against the current version of WinDriver.

7.4.1. Regenerating code and gradually merging

If your code is very old, the most recommended method is to generate a new project for your device using the DriverWizard of the new WinDriver version and gradually merge all device-specific code from your legacy code into the generated skeletal code.

This is the recommeneded method as it allows you to make sure that the driver still works and compiles correctly step by step, and stop and debug at any moment that behavior is not as desired (As opposed to trying to compile an old code against the new WinDriver version, where it may be harder to just get it to compile). Most of the steps in this chapter will happen by themselves/be skipped if you choose to follow the first method.

7.4.2. Checklist for Driver Code upgrade

If you must not regenerate code with the wizard as described in the previous section, the following is a list of action items to verify when upgrading a WinDriver based code.

7.4.2.1 Register Your New License

If you are using a registered version of WinDriver, contact Jungo Connectivity at wd_li.nosp@m.cens.nosp@m.e@jun.nosp@m.go.c.nosp@m.om to acquire a WinDriver license registration string for the new version. Then register the new license from DriverWizard File/Register WinDriver and from your code.

ℹ️ Note

If you have a valid license subscription you are are entitled to receive a new license free of charge. In case you do not have such a plan, contact sales.nosp@m.@jun.nosp@m.go.co.nosp@m.m to request a temporary license that will allow you to evaluate the new version.

  • Modify the driver code to register your new license — i.e., replace the license string in the call to WDU_Init() (USB) / WDC_DriverOpen() (PCI/ISA — WDC API) / WD_License() (low-level API) from your code.
  • PCI users — if you created a Kernel PlugIn driver, make sure to also update the license string in your Kernel PlugIn code.

7.4.2.2 Conform to API Updates

Some functions and APIs have changed in the course of the years, make sure your WDAPI function calls are correctly formulated.

Linking your projects with the high-level WinDriver-API DLL / shared object — wdapi<version> (version 8.x+) / wd_utils (version 7.x) — frees you of the need to include the source files from the WinDriver/src/wdapi directory (version 8.x+) / WinDriver/src directory (version 7.x) in your project.

In version 8.0.0 the name of the DLL/shared object module was changed from wd_utils to wdapi(version) (e.g. wdapi1440 in version 14.4.0) as part of the addition of versioning support to this module. This enables you to upgrade your driver, including the DLL/shared object, without worrying about the possible effects on other drivers, developed with earlier versions of WinDriver, which may be using the same module.

On Windows, in version 8.x and newer, you can use the WDAPI DLL — wdapi<version>.dll
(found in the WinDriver\redist directory) by linking your project with the
WinDriver\lib\<CPU>\wdapi<version>.lib library
(e.g. WinDriver\lib\x86\wdapi1620.lib) — for MS Visual Studio(Visual C++) projects. Similarly, the name of the WinDriver .NET API DLL changed in version 8.0.0 from wdapi_dotnet.dll to wdapi<version>_dotnet.dll (e.g.wdapi1620_dotnet.dll), and the DLL was moved to the WinDriver\lib\<CPU>\<.NET version>\directory (e.g., WinDriver\lib\x86\4\).

On Unix based OSes, such as Linux, MacOS and Solaris (Solaris was supported until 9.0.1), in version 8.x and newer you can use libwdapi<version>.so by linking your driver project with WinDriver/lib/libwdapi<version>.so (e.g. libwdapi800.so in WinDriver version 8.0.0). To link your Linux project with this shared object, add wdapi<version> to the makefile’s link flag (LFLAGS += -l wdapi<version>; e.g., LFLAGS += -l wdapi800), instead of listing all the source files from the WinDriver/src/wdapi directory (previously WinDriver/src/ — see below) in the makefile (under the SRCS flag). On all platforms, the sample and generated DriverWizard projects demonstrate how to correctly link the project with the relevant DLL/shared object for your WinDriver version and target OS.

⚠ Attention

If your code uses the high-level WinDriver-API DLL / shared object, you will need to distribute wdapi<version>.dll (version 8.x+) / wd_utils.dll (version 7.x) — for Windows, or wdapi<version>.so (version 8.x+) / libwd_utils.so (version 7.x) — for Linux and Solaris, with your driver. Windows .NET users should also distribute wdapi<version>_dotnet.dll.

WinDriver source files location changes

In version 8.0.0 the WinDriver C source files were moved from the WinDriver/src directory to the WinDriver/src/wdapi/ directory. The .NET source files were moved from the WinDriver/wdapi.net/ directory to the WinDriver/src/wdapi.net/ directory.

If you have selected to upgrade your version 6.2.x project to use the wdapi (version 8.x+) DLL/shared object, this should not normally affect you. However, if your project directly includes WinDriver source files, you may need to modify your project/make file to point to the new source files location.

Update your project’s files search paths

Beginning with version 7.0.1, the include path in the WinDriver project/make files contains the path to the WinDriver/ and WinDriver/include/ directories, and the #include statements in the WinDriver source files and generated DriverWizard code were consequently modified to indicate only the name of the header file to include, instead of the full/relative path to the file (as done in earlier versions). In light of these changes, when rebuilding a driver project from version 7.0.0 or earlier of WinDriver with the source files from version 7.0.1 or newer, you may need to modify your project/make file and add the path to the WinDriver/ and WinDriver/include/ directories to the project’s include path in order to successfully build the project.

For USB, beginning with version 7.0.0 of WinDriver, if you have created a console driver application/DLL/shared object that calls functions implemented in WinDriver/samples/c/shared/usb_diag_lib.c (as is the case for the sample and generated WinDriver USB diagnostic driver projects), to build your project with the usb_diag_lib.c file from the new version you must add the new WinDriver/samples/c/shared/diag_lib.c file to your project. For PCI/ISA users, beginning with version 7.0.0 WinDriver features the high-level WDC library, which provides convenient wrapper APIs to the standard WinDriver PCI/ISA APIs. (This library is part of the wdapi<version> (v8.x+) / shared object (see above; the source files are found under the WinDriver/src/wdapi directory (v8.x+) . The WDC APIs are documented in this manual. The generated DriverWizard v7.x+ projects use the WDC APIs instead of the low-level WD_xxx APIs. The WDC APIs are also used from the v7.x+ pci_diag, pci_dump and PLX samples. Since WDC mainly provides wrappers to the standard WinDriver APIs, which are still supported, you do not need to modify your old code to use the new WDC library. Should you select to upgrade your code to use the WDC APIs, you can examine the new samples and generated code and compare them to those from your old WinDriver version for a better understanding of how to use the new APIs.

⚠ Attention

To use the WDC APIs you will need to either include the relevant wdc_xxx.c source files from the WinDriver/src/wdapi directory in your project/makefile; or link your project with the wdapi<version>WinDriver high-level API DLL/shared object.

7.4.2.3 64-bit OS upgrade (Windows and Linux)

When porting your driver from a 32-bit platform to a 64-bit platform, 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 Windows MS Visual Studio projects in the 64-bit WinDriver toolkit already add this definition.

7.4.2.4 Rename your driver (Windows and Linux)

To avoid conflicts with other WinDriver-based drivers on the target platforms, we highly recommend that you rename the default WinDriver driver module — windrvr(VERSION).sys(e.g., windrvr1620.sys) on Windows / windrvr(VERSION).o/.ko(e.g., windrvr1620.o/.ko) on Linux (or windrvr6.sys / windrvr6.o/.ko in versions 11.8.0 and older) — to a unique name, by following the instructions in (Chapter 15: Distributing Your Driver). The Linux USB GPL driver — windrvr(VERSION)_usb.o/.ko (or windrvr6_usb.o/.ko in version 11.8.0 and older) is automatically renamed when renaming the main WinDriver Linux driver. When creating a PCI Kernel PlugIn driver, select a unique name as well.

7.4.2.5 Ensure that your code uses the correct driver module

Verify that the call to WD_DriverName() in your driver code (if exists) uses the new driver-module name — windrvr(VERSION) or your renamed version of this driver. In version 11.9.0 of WinDriver the default WinDriver driver-module name changed from windrvr6 to windrvr(VERSION)(e.g., windrvr1620). Consequently, when using the default driver-module name old projects need to be updated to use the default name from the newer version. 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, ensure that your code calls WD_DriverName() 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. To apply a driver name change — whether using the default driver name or a custom name — your user-mode driver project must be built with the WD_DRIVER_NAME_CHANGE preprocessor flag (e.g., -DWD_DRIVER_NAME_CHANGE).

7.4.2.6 Rebuild your updated driver

Rebuild your updated driver project with the source files from the new version.

PCI users who created a Kernel PlugIn driver must rebuild it with the files from the new version as well.

7.4.2.7 Upgrade Your Device INF File (Windows)

On Windows, you must create and install a new INF file for your device, which registers it with the driver module from the new version windrvr(VERSION).sys (e.g., windrvr1620.sys) / windrvr6.sys in version 11.8.0 and older — or your renamed version of this driver (in version 9.x and newer). You can use DriverWizard from the new version to generate the new INF file, or change the driver version in your old INF file.

7.4.2.8 Digitally Sign Your Driver Files (Windows)

Microsoft requires that kernel drivers to be digitally signed. Therefore, if you use any of the following driver files you must digitally sign them. A renamed version of the WinDriver kernel driver (the default WinDriver driver — windrvr(VERSION).sys / windrvr6.sys in version 11.8.0 and older — is already digitally signed), a Plug-and-Play device INF file, and/or a PCI Kernel PlugIn driver. For more info see 17.3. Windows Digital Driver Signing and Certification.

ℹ️ Note

If you have any any questions in regard to driver digital signature, please send an e-mail to WinDr.nosp@m.iver.nosp@m.@jung.nosp@m.o.co.nosp@m.m. Our team will answer any questions you may have and provide full assistance.

7.4.2.9 Upgrade Your Driver Distribution/Installation Package

Create a new driver installation package that contains the relevant files from the new WinDriver distribution, depending on your hardware and target OS. Hardware and OS-specific driver distribution instructions can be found in Chapter 15: Distributing Your Driver.

⚠ Attention

Do not try to use WinDriver related files (shared libraries, etc.) from older versions in your new distribution package as they will not work with the newer version.

7.4.2.10 Check for changes in variable and struct sizes

Upon switching platforms, operating systems or environments, the default sizes of basic types such as int, long etc. may change. If you are changing a platform, make sure that these changes do not affect your code by careful debugging. When upgrading code from WinDriver versions older than 14.9, make sure to address the changes made to the DWORD typedef, which is widely used in WinDriver's sample and generated code. For more information, see 7.5.2 64-Bit and 32-Bit Data Types.

7.5. 32-Bit Applications on 64-Bit Windows and Linux Platforms

By default, applications created using the 64-bit versions of WinDriver are 64-bit applications, and application created using the 32-bit versions of WinDriver are 32-bit applications. However, you can also use the 64-bit WinDriver versions to create 32-bit applications that will run on the supported Windows and Linux 64-bit platforms.

⚠ Attention

WinDriver for MacOS currently supports only 64-bit applications.

We recommend avoiding compiling your applications in this manner unless you have to, as this might introduce a performance decrease for your driver.

In the following documentation, (WD64) signifies the path to a 64-bit WinDriver installation directory for your target operating system, and (WD32) signifies the path to a 32-bit WinDriver installation directory for the same operating system.

To create a 32-bit application for 64-bit Windows or Linux platforms, using the 64-bit version of WinDriver, do the following:

  • Create a WinDriver application, as outlined in Chapter 6: Using DriverWizard (e.g., by generating code with DriverWizard, or using one of the WinDriver samples).
  • Build the application with an appropriate 32-bit compiler for your target OS, using the following configuration:
  • Make sure that KERNEL_64BIT preprocessor definition is added to your project or makefile. 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.
  • 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\wdapi1620_32.lib on Windows / (WD64)/lib/libwdapi1620_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, CMake or Windows GCC makefiles are defined to link with (WD64)\lib\amd64\x86\wdapi1620.lib. On Linux, the installation of the 64-bit WinDriver toolkit on the development machine creates a libwdapi1620.so symbolic link in the /usr/lib directory — which links to (WD64)/lib/libwdapi1620_32.so — and in the /usr/lib64directory — which links to (WD64)/lib/libwdapi1620.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\wdapi1620_32.dll on Windows /(WD64)/lib/libwdapi1620_32.so on Linux. 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.

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\wdapi1620.lib on Windows / (WD32)/lib/libwdapi1620.so on Linux); and it should be distributed with the standard 32-bit WinDriver-API DLL/shared object ((WD32)\redist\wdapi1620.dll on Windows / (WD32)/lib/libwdapi1620.so on Linux) and any other required 32-bit distribution file.

7.5.1. Developing a 32-Bit Application for Both 32-Bit and 64-Bit Platforms

If you have both 64-bit and 32-bit WinDriver installations, you can also create a single 32-bit application that can be executed on both 32-bit and64-bit platforms. This can be done using the following method:

  • Create a DLL (on Windows) or a shared object (on Linux) that concentrates the calls to the WinDriver APIs. If you created a WinDriver application using the generated DriverWizard code or one of the WinDriver samples, convert this application to a DLL/shared object.

⚠ Attention

When using DriverWizard to generate PCI driver code for Windows MS Visual Studio, you have the option to generate the library code as a DLL (for both 32-bit and 64-bit environments).

  • Compile two versions of your DLL/shared object:

A version for 32-bit platforms: This version should be compiled using a 32-bit compiler, without the KERNEL_64BIT definition, and linked with the standard 32-bit WinDriver-API library/shared object from the 32-bit WinDriver installation — <WD32>\lib\x86\wdapi<ver>.lib on Windows (e.g.,C:\WinDriver\lib\x86\wdapi1200.lib) /<WD32>/lib/libwdapi<ver>.so on Linux (e.g.,~/WinDriver/lib/libwdapi1200.so). A version for 64-bit platforms: This version should be compiled using a 32-bit compiler, with the KERNEL_64BIT definition, and linked with the standard 32-bit WinDriver-API library/shared object from the 64-bit WinDriver installation — <WD64>\lib\amd64\x86\wdapi<ver>_32.lib on Windows (e.g., C:\WinDriver64\lib\x86\wdapi1200.lib) / <WD64>/lib/libwdapi<ver>_32.so on Linux (e.g., ~/WinDriver64/lib/libwdapi1200_32.so) (see details above regarding compilation of 32-bit applications for 64-bit platforms).

  • Write a 32-bit application that communicates with WinDriver via the DLL/shared object that you created: the application should be implemented to load the relevant version of the DLL/shared object — 32-bit or 64-bit — depending on the platform on which it is run.

⚠ Attention

This application should be compiled using an appropriate32-bit compiler, without the KERNEL_64BIT definition.

When distributing a driver that was developed using this method, be sure to distribute the relevant files for each target platform:

For 32-bit platforms, distribute the application together with the 32-bit version of your WinDriver-wrapper DLL/shared object, and with the standard 32-bit files from the 32-bitWinDriver installation, including the 32-bit WinDriver DLL/shared object
(<WD32>\redist\wdapi1620.dll on Windows / <WD32>/lib/libwdapi1620.so on Linux).
For 64-bit platforms, distribute the application together with the 64-bit version of your WinDriver-wrapper DLL/shared object, and with the standard 64-bit files from the 64-bitWinDriver installation, including the 64-bit WinDriver DLL/shared object
(<WD64>\redist\wdapi1620.dll on Windows / <WD64>/lib/libwdapi1620.so on Linux).

7.5.2 64-Bit and 32-Bit Data Types

⚠ Attention

Since WinDriver 15.00 The DWORD typedef is ALWAYS 32 bits wide.

On all previous versions the previous table has applied:

Operating System DWORD width
Windows (32 and 64 bits) 4 bytes
Linux (32 bits) 4 bytes
Linux (64 bits) 8 bytes
MacOS (64 bits) 8 bytes

When upgrading existing code from a version lower than 15.00, make sure that your code does not use DWORD variables for holding addresses or hardware related data.

  • If a variable used to be 64 bits wide in older versions and you need to keep it 64 bit wide, define it as UINT64 instead.
  • If a variable is used to hold data which is related to a WinDriver API of size DWORD (i.e. dwOptions), you could keep it defined as DWORD.

7.6. WinDriver .NET APIs in PowerShell

Microsoft defines PowerShell as “a task-based command-line shell and scripting language built on .NET. PowerShell helps system administrators and power-users rapidly automate tasks that manage operating systems and processes.”

The advantages of using WinDriver with PowerShell are:

  • PowerShell comes built-in in all modern Windows systems. No need to install any additional software to use it.
  • No need to compile your code as it is a scripting language.
  • The ability to easily combine WinDriver with your scripts or with any other .NET based library.

WinDriver has been providing its .NET wrapper DLL wdapi_dotnet1620.dll (1620 stands for the version number) for many years. Using PowerShell’s built-in .NET support you can easily open this DLL and call API functions by using the following code from PowerShell’s command line:

  • Load the WinDriver .NET DLL:
using namespace Jungo.wdapi_dotnet
$wdapi_dotnet = [Reflection.Assembly]::LoadFile($Env:WD_BASEDIR + "\lib\amd64\wdapi_netcore1620.dll")
  • Open WinDriver:
[windrvr_decl]::WD_DriverName("YOUR_DRIVER_NAME")
[wdc_lib_decl]::WDC_DriverOpen([wdc_lib_consts]::WDC_DRV_OPEN_DEFAULT, "YOUR_LICENSE_STRING")
  • Open a device - by default the slot will be set to 0,0,0,0:
$slot = New-Object -TypeName "Jungo.wdapi_dotnet.WD_PCI_SLOT"
$deviceInfo = New-Object -TypeName "Jungo.wdapi_dotnet.WD_PCI_CARD_INFO"
$deviceInfo.pciSlot = $slot
[wdc_lib_decl]::WDC_PciGetDeviceInfo($deviceInfo)
  • Device context will be set to NULL for simplicity of sample:
$pDevCtx = $NULL
$dev = New-Object -TypeName "Jungo.wdapi_dotnet.WDC_DEVICE"
[wdc_lib_decl]::WDC_PciDeviceOpen([ref]$dev, $pDeviceInfo, $pDevCtx)
  • Read from the device (or any other WinDriver API usage):
[wdc_lib_decl]::WDC_ReadAddr32($dev.hDev, 0, 0x60, 0x1)
  • Cleanup:
[wdc_lib_decl]::WDC_PciDeviceClose($dev.hDev)
[wdc_lib_decl]::WDC_DriverClose()

There is a complete PowerShell Script utilizing WinDriver’s API. Jungo provides a sample for PowerShell based on our pci_diag sample application. It is located in WinDriver\samples\powershell\pci_diag. Make sure you allow Powershell to run scripts, then do as follows:

  • Open PowerShell as an administrator and run:
Set-ExecutionPolicy RemoteSigned
  • To run pci_diag for PowerShell type:
cd $Env:WD_BASEDIR\samples\powershell\pci_diag./pci_diag

⚠ Attention

Currently the sample does not yet support the following features: Power events, IPC, Kernel PlugIn, USB, Shared Kernel Buffer. WinDriver’s API and pci_diag work on both the PowerShell command line and the PowerShell ISE IDE. Starting with WinDriver 14.70, WinDriver’s .NET 5 API can be used in on Linux or MacOSX as well, using PowerShell 7 or higher.

7.7. WinDriver Server API

The following WinDriver Server APIs are not part of the standard WinDriver API set. Also, they are not included in the standard version of WinDriver.

However, they are part of “WinDriver for Server” API and require “WinDriver for Server” separate license. “WinDriver for Server” APIs are included in WinDriver evaluation version for evaluation only.

IPC API (Inter-process communication):

Buffer sharing API:

PCI devices scanning:

SR-IOV API(Linux Only):

7.8. FAQ

7.8.1. Using WinDriver to build a GUI Application

Although most samples provided in the WinDriver package are console-mode applications, it is possible to integrate WinDriver's API into Graphic User Interface (GUI) applications. Some examples of GUI applications that were built with WinDriver are our DriverWizard and Debug Monitor (built with the Qt Framework), and also our .NET GUI samples/generated codes.

7.8.2. Can WinDriver handle multiple devices, of different or similar types, at the same time?

It is possible. For the sake of simplicity, our C, Java and Python PCI samples only allow opening one device at a time, but it is indeed possible in these languages as well. Our USB samples for C, Java and Python allow opening multiple devices at the same time. Our .NET samples also allow opening multiple devices at the same time.

Generally, each device controlled by WinDriver has its own unique handle, allowing applications to open multiple handles at the same time if needed.

7.8.3. Can I run two different device drivers, both developed with WinDriver, on the same machine?

Yes. You can run several WinDriver-based applications simultaneously on the same machine. It is strongly recommended that the WinDriver Kernel Module will be renamed in that case.

7.8.4. Can WinDriver group I/O and memory transfers?

Yes. Using WinDriver, you can group I/O and memory transfers by calling WD_MultiTransfer(), which can perform multiple transfers in one call. However, Jungo generally recommeds using the High-Level API (WDC_xxx) for I/O.

Note that you can also access the memory directly from your user-mode application using the virtual user-mode mapping of the physical address, which is returned by or WDC_PciDeviceOpen() in (((PWDC_DEVICE)hDev)->cardReg.Card.Item[i].I.Mem.pUserDirectAddr or WD_CardRegister() in cardReg.Card.Item[i].I.Mem.pUserDirectAddr, where i is the index item of the relevant memory item in the WD_ITEMS Item array.

7.8.5. I need to define more than 20 "hardware items" (I/O, memory, and interrupts) for my ISA card. Therefore, I increased the value of WD_CARD_ITEMS in the windrvr.h header file (due to the definition of the Item member of the WD_CARD structure as an array of WD_CARD_ITEMS WD_ITEMS structures). But now WD_CardRegister() will not work. Why?

If you need to define more than WD_CARD_ITEMS items for your card (currently 128 items, according to the definition of WD_CARD_ITEMS in windrvr.h), do not modify the value of WD_CARD_ITEMS in the code, but instead, simply call WD_CardRegister() several times from your code, with different items each time. It is not mandatory to lock all the resources on a specific card with a single WD_CardRegister() call. Alternatively, consider grouping several memory/IO address ranges into a single BAR definition, so that the overall resources item count does not exceed the default 20 items limit.

We highly recommend against changing anything in windrvr.h. The effect will certainly not be what you expect and it could be potentially disastrous.

7.8.6. I have a WinDriver based application running on a certain operating system, how do I port my code to a different operating system?

WinDriver generally rids you of the need to do any changes in your program's code. Of course some OS specific functions that you have been using that are not from the WinDriver API might not work anymore (i.e. Win32 functions that are not provided by POSIX, or the other way around), but this is why we recommend trying to stick only to cross-platform standard functions in your C code and to the WinDriver API. There are about 10% of WinDriver's API features that are not cross platform, but usually this could be overcome with different alternatives. If this could not be overcome, contact Jungo Support for assistance.

The recommended and easiest way to shift between platforms is to generate a CMakeLists.txt file for your project using the DriverWizard. This will allow you to port the code over all supported OSes and makes the porting a much easier task, assuming you've installed CMake on your target development machine.

On supported languages other than C, porting should be even easier as these languages support cross-platform use inherently.

Assuming you're using a renamed driver - a step you will have to go through is creating a new project from the DriverWizard in your new operating system. This will create a renamed driver for your target platform (i.e. if you had a .sys file for your driver on a Windows system, then on Linux the wizard would create a .ko file, etc.).

As described in 7.4.1. Regenerating code and gradually merging, the best way for this kind of porting is first to generate new code with the DriverWizard, make sure that it works without any modifications, and then gradually merge your code from the other operating system into your new OS code.