In keeping with the general goals of Gadgeteer, device driver authors should strive to achieve certain goals for each device driver they write. In no particular order, we feel that the most important goals are the following:
Portability
Maintainability
Efficiency
Modularity
For the most part, these goals are no different than those of any other software project. Nonetheless, we will explain why each is important in the following subsections.
Gadgeteer is a cross-platform device management system, and as such, the devices it manages should be usable on all platforms supported by Gadgeteer. While this may not always be possible[2], device driver authors should still attempt to make their drivers as portable as possible. The VR Juggler Portable Runtime (VPR), introduced later in Chapter 2, Using the VR Juggler Portable Runtime, provides many features that simplify the work of writing portable software. This applies to device drivers as much as any other piece of software, and thus, programmers should make use of VPR whenever possible.
Hardware tends to evolve over time, and new versions of a given device may be released. With new hardware, the communication protocol may change, either through extensions or through extensive changes. In order for Gadgeteer device drivers to be used with new hardware, a driver must be written so that it can be maintained by other programmers. That means that a driver should be documented well, and it should not use complex techniques to communicate with the hardware.
Based on our experience, we recommend that the following practices when writing a new driver:
Do not “brute force” the driver implementation just to get something working. Implement the protocol clearly and completely.
Do not hard-code maximum values to match a local installation or the current limitations of the hardware. For example, if a positional tracker at the local facility only has two trackers attached to it, do not assume that everyone else has the same configuration.
Do not do tricks with memory buffers. C and C++ provide very nice features for accessing blocks of memory, so there is usually no need to do pointer math by hand. More often than not, a struct or a union will do a much better job than an array of bytes.
Input devices used with virtual reality systems tend to sample at a much higher rate than the graphics are rendered (1000 Hz versus 60 Hz). Thus, for a given frame, the driver may make tens or hundreds of samples. Gadgeteer provides some facilities for efficient collection of samples, but ultimately, the driver author must ensure that the driver will not overwhelm the local computer (or the network if the Remote Input Manager is being used). On the other hand, minimizing input latency is very important in achieving good suspension of disbelief on the part of the user. Thus, it is not advisable to discard samples.
The key thing to keep in mind when writing a device driver for Gadgeteer is that the driver will be running asynchronously from the graphics. Usually, the sample rate will be limited by how fast the sample can be read from the hardware, be it a memory access, a serial port read, or a network buffer read. A balance between low latency, memory efficiency, and possibly network efficiency must be found.
The current practices used in Gadgeteer encourage modularity of device drivers. Each driver should be able to stand on its own as a single unit within the Input Manager. This philosophy allows individual drivers to be loaded on demand at runtime, and it simplifies compilation of drivers that are not supported on all operating systems.
[2] There are various reasons why a given hardware device may not be usable between computers. For example, not all architectures have parallel ports, and thus, a parallel port device could not be expected to be used where no port is available. In general, however, the software device driver should not be the limiting factor in the use of a hardware device.