I was as fascinated with the Nintendo Wii gaming console as the rest of the world was when it came out and thought its unique input system was jaw-dropping awesome. I subsequently happened to stumble upon some incredibly creative work by Johnny Chung Lee on the internet one day where he demonstrates how the Wii remote - also known as the Wiimote - can be used to build innovative new ways of interacting with a computer. He got me so excited with the idea that I almost immediately went out and got a Wiimote myself though I don't even own the Wii console!

When Windows 7 came out and I learnt about the new Sensor and Location Platform, I figured writing up a little bridge driver that exposed the 3-axis accelerometer that each Wiimote comes with to the sensor platform would be kind of cool. This article attempts to explain how the driver works and what it takes, in general, to write a driver for the Sensor platform.

The implementation of the Wiimote sensor driver, particularly the communication protocol implementation, has been heavily "inspired" by Brian Peek's WiimoteLib library which has turned into a sort of de-facto standard API for gaining access to the Wiimote from managed code via the Windows HID API. Also, the sample driver implementations from the Windows Driver Kit provided the starting point to get the project off the ground. The I/O management code was taken with some slight modifications from the Sensor Development Kit.

If you're looking to just use the driver and don't really care how it works, then here's what you've got to do. The Wiimote is a surprisingly self-contained piece of hardware that really is a stand-alone product by itself. It communicates with the Wii console via standard Bluetooth radio signals and identifies itself as a HID input device. To make it work with your computer, here's what you'll need:

A Wiimote (duh!)

A computer with Windows 7

A Bluetooth card

There have been some reports out there where people had trouble getting their Bluetooth driver stack to recognize the Wiimote. If you're one of them you'll probably need to get updated drivers for your Bluetooth card. Assuming your computer is able to pair with the Wiimote, here's how you do it in Windows 7.

Click the "Start" button, type "bluetooth" into the search box and select "Add a Bluetooth device".

Press the 1 and the 2 buttons on the Wiimote at the same time. You should see the 4 blue LEDs blinking. Keep both the buttons pressed until the pairing is complete.

You should now see the Wiimote show up in the "Add a device" window. Select the Wiimote and hit "Next".

In the "Select a pairing option" screen click "Pair without using a code".

You'll see the following screen next. This does not however mean that the pairing was successful. If you look in your system tray you'll see the system trying to locate a driver and install it. Windows will try to find a driver for the device on Windows Update first and that usually takes a while to complete - you can expedite the process by cancelling the look up on Windows Update.

Once the driver installation is complete, you should see this in the system tray area if everything went well.

And in your Bluetooth devices window you should see the Wiimote listed as a game controller device.

Now, you're probably seeing the 4 LEDs on your Wiimote continue to blink non-stop. I suggest you run Brian Peek's "WiimoteTest.exe" tool (which is included in the "tools" download provided along with the downloads for this article) about now and have only 1 of the LEDs light up so you know it's on. Also, running "WiimoteTest.exe" appears to initialize the Wiimote somehow and is required to get the sensor driver talking with the Wiimote. I hope to figure out what exactly "WiimoteTest.exe" does to initialize the Wiimote and do that from the sensor driver also one of these days.

To install the Wiimote sensor driver so it shows up as a sensor in your system, here's what you need to do:

Download the relevant binaries package depending on the number of bits your CPU can grok in a single cycle. In other words if you have a 32-bit CPU then download the 32-bit version of the binary and if you have a 64-bit CPU then download the 64-bit version. Unzip it somewhere - I'll assume you unzipped it to "C:\Wiisensor".

Download the tools ZIP file and unzip it to the same location that you used in step 1.

Open a command prompt with administrator privileges and navigate to "C:\Wiisensor".

Now, depending on whether you are running a 32-bit or a 64-bit version of Windows 7 navigate further to either the "i386" folder or the "amd64" folder in the command window. If you're on a 64-bit edition of Windows 7 then run the following command (all on one line):

If you are presented with an unsettling dialog such as this one, just hit "Install this driver software anyway":

You're seeing this because the driver needs to be signed with a trusted digital certificate - which it would be had this been a commercial driver.

Once the installation is complete you should be able to see the device listed under the "Sensor" class in device manager (you can launch the device manager by clicking "Start" and typing "device manager" into the search box).

As you can see, the Wiimote is listed not once, but twice! I haven't quite figured out why it does this, but it is safe to simply uninstall the entry that shows with a yellow exclamation mark next to it. Simply right click on the entry and select "Uninstall".

The final step is to enable the sensor in the sensors control panel. Click "Start" and type "sensors" into the search box and select "Location and Other Sensors".

Check the "Enabled" box against the "Nintendo Wiimote" entry in the sensors control panel and hit "Apply".

And that's it! Now you're ready for business! I know you're thinking that all this is way too complicated and I agree. But in a real app all this should ideally be taken care of by an installer app and end users wouldn't need to have to mess with this stuff.

If you are with me so far, then you should be able to launch the "Wiidiag" tool from "C:\Wiisensor\bin\Wiidiag\Wiidiag.exe" and watch a dull little graph respond to you whenever you wave your Wiimote around!

Now, what's cool is that you can pretty much get any app off the shelf and have it work with your Wiimote's accelerometer if it is designed to work with the Sensor platform. You could for instance, download the plane demo app from here and it should just work! In fact I have included the binary for that demo with the download for this article and you should find it in "C:\Wiisensor\tools\PlaneDemo\DemoApp.exe". When you launch it you should see a little plane model rendered on the screen. Just check the 3 check boxes representing the 3 axes and it should immediately start rotating the plane around as you move the Wiimote.

The Windows Sensor and Location Platform is a new framework on Windows 7 designed to make it easy for hardware vendors and application developers work seamlessly with sensor devices. Here's some standard palaver from Microsoft:

The Windows Sensor and Location platform, which is new for Windows 7, enables your computer and applications to adapt to their current environment. With location sensors -- including GPS devices, WWAN radios, and even triangulation technology -- your applications and gadgets can know exactly where they are, enabling them to provide more locally relevant content and functionality. Ambient light sensors, for example, can allow your computer to automatically adjust your screen's brightness based on the current lighting conditions. They can also enable applications to optimize their content for readability, making your computer more useful in a range of operating environments than ever before.

The platform provides a standard way to integrate sensor and location devices into Windows, as well as a standard programming interface for applications to take advantage of these devices. On Windows 7, the user has control over how data from these devices is exposed to applications.

Sensor client apps can be written using the new Sensor API which is basically a COM based unmanaged API. But Microsoft has however, provided helpful little managed wrapper classes as part of their Windows 7 API code pack, which you can download from here. The "Wiidiag" sample app that comes with the download for this article for instance is an example of how straightforward the API is to use.

You first setup a reference to the "Microsoft.WindowsAPICodePack.dll" and the "Microsoft.WindowsAPICodePack.Sensors.dll" files and use the SensorManager class to gain access to the sensors installed on the system. Here's the code from "Wiidiag" that initializes a drop down with all the "Motion" sensors installed on the system.

The StateChanged event fires whenever something of note happens to the sensor such as when it becomes available or when it goes away. The DataReportChanged event fires whenever the sensor has some data to provide to the app. The Wiimote accelerometer data for instance, is made available via this event.

Here's the code from "Wiidiag" for handling the DataReportChanged event. It essentially simply adds the new data sample to the graph user control.

Now, writing a sensor driver is a tad more complicated, as you might expect and is in fact the focus of the rest of this article. Having said that, you really should not let that scare you as writing a sensor driver is nothing like writing drivers in the traditional sense, i.e. if you're thinking endless machine restarts and the blue screen of death (BSOD) - rest assured that the experience isn't at all like that primarily because sensor drivers are written using the User Mode Driver Framework (UMDF). Before I can tell you how a sensor driver works, I'll need to give you a brief primer on how UMDF drivers work. If you already know how a UMDF driver is built, then feel free to skip the next section.

Describing how to write a UMDF driver is sophisticated enough to warrant a separate article in its own right and I am not therefore, going to try and attempt to explain every nuance of it. In fact I myself am only a beginner and won't pretend that I know all that there is to know about it. I will however try and depict how I visualize the framework in my head. Folks over at OSR have written a nice little overview of what it takes to implement a UMDF driver here. An architectural overview is available here from the same site.

The basic idea behind the UMDF is that for a certain class of drivers, it simply is not worth the pain of implementing a kernel mode driver when the same can be achieved with code running in user mode. Here're some obvious benefits from having your driver run in user land (taken from the UMDF FAQ).

Increased stability. User-mode drivers can crash or hang only their own process, not the entire system.

Ease of development. User-mode drivers can be written in C++ and debugged by using user-mode debuggers, without requiring a separate debugging system.

Increased security. User-mode drivers do not have access to the kernel-mode address space and therefore cannot expose kernel-mode data, such as system information or data belonging to other processes.

The most important benefit is of course that a driver crash does not mean a BSOD and a system restart. Instead, the process hosting the UMDF driver can simply be terminated and then restarted. As a developer, the fact that you can use the debuggers that you love (Visual Studio for instance) for your regular user mode application development is an added bonus.

The next section describes just enough of UMDF so that you can appreciate how the sensor driver works. It does not, for instance, try to explain all the different ways that a UMDF driver can handle I/O.

A UMDF driver is a regular windows DLL. The framework uses a COM based development environment without actually using the COM runtime library. The COM-connection exists almost solely for managing object lifetimes and for type introspection which translates to the requirement that all UMDF objects must implement IUnknown.

Life in a UMDF driver begins with an object that implements the interface IDriverEntry. This interface has only 3 methods in it with the key one being OnDeviceAdd which is invoked by the framework when a device of interest arrives in the system. The driver is expected to respond to the OnDeviceAdd call by creating an IWDFDevice object and hooking it up with a object that the driver provides which in turn implements all of the callback interfaces containing event notifications that the driver is interested in being notified with.

In the Wiimote sensor driver for example, the class CWiimoteDriver implements IDriverEntry. In its OnDeviceAdd method, it calls the static method CWiimoteDevice::CreateInstance which in turn instantiates an IWDFDevice object and associates it with an instance of CWiimoteDevice via IWDFDriver::CreateDevice. CWiimoteDevice implements the IPnpCallback, IPnpCallbackHardware and the IFileCallbackCleanup interfaces which contain callback methods that are invoked by the framework at various points. IPnpCallback for instance, contains methods that are called whenever a plug-and-play device enters and exits the system.

Here's a sequence diagram that might help illustrate the flow of control in a UMDF driver as it loads.

The CWiimoteDevice class implements IPnpCallback, IPnpCallbackHardware and IFileCallbackCleanup. The key interface here is IPnpCallbackHardware which contains 2 methods - OnPrepareHardware and OnReleaseHardware. OnPrepareHardware is called by the framework to indicate that the driver should do everything that is necessary to prepare the device for access and OnReleaseHardware is called to have the driver perform clean-up after the device stops being accessible. CWiimoteDevice::OnPrepareHardware bootstraps the sensor framework by initializing all the sensor objects, the sensor class extension object (explained later in the article) and the object that implements ISensorDriver (again, explained elsewhere).

CWiimoteDevice's implementation of the IPnpCallback interface does something useful only in the CWiimoteDevice::OnD0Entry and the CWiimoteDevice::OnD0Exit methods where it instructs all the sensor devices in the driver to start and stop I/O operations respectively.

Like all drivers, UMDF drivers are also installed using an INF file as the source. Among other things, the INF file describes:

what driver class the driver belongs to

what version of the OS the driver requires for it to work

what device the driver is built to work with

what files must be included in the driver package and where they must be copied during the install

the driver version and time-stamp

The Windows device manager uses this information to correctly install and configure the driver. For UMDF drivers, one other critical piece of information is the COM CLSID of the object implementing IDriverEntry as without this the framework cannot really boot the driver up. For a detailed explanation of how INF files work I suggest you take a look at the MSDN documentation.

Beyond this point, control shifts to the sensor framework. Before we delve into that however, it is necessary that we take a short detour looking into how the build system for the Wiimote sensor driver works.

If you, like me, have been spoiled by Visual Studio in developing, debugging and testing applications you might feel as at sea as I felt initially when working with UMDF where you are pretty much forced to use the build environment that the Windows WDK installs for you. But some of the saintly folks at OSR have taken the effort to build a batch file that allows you to integrate the WDK with Visual Studio and build and code from right within the IDE. In the next few sections I explain the things you need to setup on your machine before you can hit Ctrl+Shift+B (or just F7 if you've got the VC++ keyboard bindings setup in VS as I have).

You might be wondering what's the deal with downloading UnxUtils. I'll explain the exact role that this plays later on in this section but I basically use some of the UNIX tools such as "sed" to automatically update build revision numbers.

Make sure that the system PATH environment variable has been updated to point to the "\usr\local\wbin" folder of your UnxUtils installation. This is required so that the build system can invoke the UNIX tools simply by name.

The Visual Studio project for the driver is a VC++ Makefile project. Makefile projects are basically projects where the actual building of the binaries are delegated to an external script/batch file. Visual Studio can be configured to invoke an external command (such as makefile) whenever you build your project. VS will automatically parse the output from the command and list the errors and warnings directly in the IDE if they are printed in standard forms such as those produced by the VC++ compiler so that double-clicking on an error will directly take you to the offending line. The next few sections describe how this process works.

As I had explained earlier, building drivers (user mode or otherwise) using the WDK requires you to launch the relevant build environment depending on the CPU architecture and operating system you are targeting and issuing the build command. The build utility uses a file called "sources" to determine what the source files are and how the binary must be built. The "sources" file used for the Wiimote sensor driver project is a fairly standard one except for a couple of things:

I added the USE_STL = 1 directive as I have grown to love and adore the STL container classes.

I customized the flags passed to the C++ compiler using the USER_C_FLAGS = /EHsc /wd4238 directive as I needed exception handling support (which /EHsc enables). The /wd4238 flag prevents the compiler from issuing warning 4238. This was needed because a certain line of code in the project causes the compiler to issue this warning and WDK builds are by default configured to treat all warnings as errors. I happen to believe that this particular warning can be safely ignored in this case.

Now that we have the "sources" file in place we should be able to launch a WDK build environment and run build -ceZ to do a clean rebuild. To be able to do this from Visual Studio however I used the DDKBUILD batch file from OSR as the external build command for the VS Makefile project. The article at that link describes how the batch file works. I created separate VC++ build configurations for building x86 32-bit and 64-bit versions of the driver. So, to build a 32-bit version of the Wiimote driver, simply select the current configuration as "Debug32" or "Release32" depending on whether you want a debug or a release build (also called as a "checked" or "free" build in the driver community) and hit F7 (or Ctrl+Shift+B). You'd select "Debug64" or "Release64" to get the corresponding 64-bit versions. Here're the build and rebuild settings for all the 4 configurations:

Being a driver, you can't just hit F5 to start a debugging session because the driver is loaded in the UMDF host process on-demand when a device that needs the driver shows up on the system. Debugging UMDF drivers has been adequately explained in MSDN and that is your best bet for figuring out how to do it. I personally used the technique as described here to attach to the UMDF host process when the driver loads. The host process is called "WUDFHost.exe" and you can attach to this process immediately after you have installed the driver using devcon.exe. I set the HostProcessDbgBreakOnStart value in the registry to 60 seconds so that I have adequate time to attach to the host process.

The only tricky part here is figuring out which instance of "WUDFHost.exe" to attach to as chances are there are multiple instances running at a given point in time. I usually just attach to all the running instances. Sometimes I'd attach to all the running instances and find that the driver DLL does not load - this usually means that a new host process was launched after I'd attached to all the existing hosts.

It turns out that the Windows device manager caches driver installation files (in "C:\windows\system32\DriverStore\FileRepository" on Windows 7) the first time that you install it and will always pick the files from the cache during a subsequent reinstall/update unless the new files have an updated version number. This is a bit of a pain during a standard build-deploy-debug cycle because you have to remember to manually update the RC file and the "WiimoteSensor.inf" file with a new version number every time you build. I decided to automate this little bit so that every time I created a new build from VS, it'd automatically increment the version numbers. Here's how this works for the Wiimote sensor project:

DDKBUILD supports the execution of pre/post build tasks by creating files called "ddkprebld.cmd" and "ddkpostbld.cmd" in the folder where you have all of your source files. In "ddkprebld.cmd" I call another batch file called "incv.bat" inside the "mbld" folder to have it update the version numbers.

"incv.bat" uses 2 other batch files called "incm.bat" and "incr.bat" to increment the version numbers in the "makefile.inc" and the "WiimoteSensor.rc" files.

All these script files primarily use the UNIX "sed" tool to look for and update the specific string in the source file that is to be updated.

While the sample drivers that the WDK comes with for sensor drivers give you a general idea of how to go about writing sensor drivers, I personally found the way the code was structured quite confusing. I decided to re-factor things a little when writing the Wiimote sensor driver. This section seeks to explain how I went about implementing the core driver.

The primary task of a sensor driver is to, well, sense things and report data! From a sensor driver's perspective the outside world is represented via a pointer to an object implementing the interface ISensorClassExtension. This object is provided by the sensor platform and acts as the broker between the driver and the client apps that are interested in the data that the sensor makes available. From the ISensorClassExtension object's perspective, the sensor driver is an object that implements ISensorDriver. The ISensorDriver object is provided by the driver and contains various methods that are invoked at different points by the sensor platform as needed. The key responsibilities of the sensor driver are:

Manage I/O with the sensor hardware device.

Manage sensor properties and data.

Track client apps that connect to the sensor and honor client app preferences.

Each sensor supported by the sensor driver is essentially a collection of properties and data. Properties are different from data in the sense that "properties" are usually attributes - such as the friendly name of the sensor, the name of the manufacturer, the model number etc. - attributes that tend to stay static. And "data" is, well, data! In the case of the Wiimote sensor driver, the acceleration values reported by the Wiimote qualifies as data.

The sensor platform requires that you report and maintain the properties and data supported by your sensor through objects implementing IPortableDeviceKeyCollection and IPortableDeviceValues. IPortableDeviceValues is basically a dictionary object where the keys are GUID values representing individual properties and the value is a PROPVARIANT which can hold pretty much anything (its the same thing as the VARIANT type in COM). IPortableDeviceKeyCollection is a collection of GUID values representing a collection of property keys.

To make the management of properties and data somewhat painless, I came up with a class called CPortableDeviceProps that almost completely shields its users from having to deal directly with the IPortableDeviceKeyCollection and IPortableDeviceValues objects. It uses the CDeviceProperty object to support seamless specification of property values in a type-independent (without sacrificing type-safety) manner. Creating the collection of data properties supported by the accelerometer for instance looks like this:

When you think about implementing ISensorDriver it turns out to be useful to think of the methods in this interface as being grouped into clusters of related functionality. I suspect that all the methods were clumped into a single interface in an attempt at keeping the requirements on the driver somewhat simple. Here's a listing of the methods supported by this interface classified into functional groups.

Client Management

OnClientConnect

OnClientDisonnect

Event Management

OnClientSubscribeToEvents

OnClientUnsubscribeFromEvents

OnGetSupportedEvents

Data Management

OnGetSupportedDataFields

OnGetSupportedProperties

OnGetDataFields

OnGetProperties

Other Methods

OnGetSupportedSensorObjects

OnProcessWpdMessage

OnSetProperties

The overall design of the sensor driver reflects this classification of functionality and the implementation of ISensorDriver mostly just delegates to other participating objects that are responsible for the relevant functional area.

The sensor driver can be visualized as being a collection of sensor objects that each manage an individual sensor. The ISensorDriver interface is implemented by the class CSensorDDI. As might be expected, all sensors share functionality that can be neatly factored into a common base class. In the Wiimote sensor driver, this class is the abstract CSensor class. What follows is a description of the key objects in the driver implementation and how they interact with each other.

CSensor

This class is the base class for all the sensor classes. In the Wiimote driver, 2 other classes inherit from CSensor - CSensorDevice and CAccelerometerSensor.

CSensor has the following responsibilities:

Manage all data and properties on the sensor.

Create and initialize properties common to all sensors.

Manage state changes and state change event notifications.

Manage I/O.

The CSensor class takes upon itself the responsibility of providing the core implementation for the "data management" methods on the ISensorDriver interface. Each sensor is identified by a unique string identifier that this class maintains.

CSensorRegistry

This class maintains a collection of references to objects inheriting from CSensor. This is the registry of sensor objects supported by the driver. It maintains a mapping between the sensor identifiers and the sensor objects. It supports enumeration of all supported sensors and the retrieval of the associated sensor object given a string identifier. Each concrete sensor class is expected to use the IMPLEMENT_SENSOR macro in one of its implementation source files to register itself with the sensor registry.

CSensorDevice

All sensor drivers are expected to support a pseudo sensor called "DEVICE" that supports some common properties. In the Wiimote driver this support is provided via this class. CSensorDevice inherits from CSensor and simply provides values for a set of properties.

CAccelerometerSensor

This is the core class implementing the accelerometer functionality. It handles the I/O with the actual Wiimote using the CReadWriteRequest class. CAccelerometerSensor inherits from CSensor and manages the properties and data unique to the accelerometer. When its StartIO method is invoked, it starts off a continuous chain of I/O read requests to the next driver stacked below the Wiimote driver. It also issues a "read memory" request on the Wiimote to read accelerometer calibration data when I/O is initiated.

The accelerometer data is parsed in the ParseAccelerationData method. This method is also responsible for raising the data event as and when new data is available. Additional information on how exactly the I/O works is provided later on in this article.

CClientsManager

This class is responsible for tracking connection and disconnection of client apps with the sensor. It implements the client management and the event management responsibilities of the ISensorDriver interface.

When I set out to build this driver, I figured that using Brian Peek's WiimoteLib library as a sort of reference for setting up I/O would be useful. Briefly, here's how I/O with the Wiimote works in the WiimoteLib.

Use HID API to enumerate all HID input devices on the system.

Inspect the product and vendor identifiers on each device and match it against the well-known product and vendor identifiers for the Wiimote (0x057E and 0x0306 respectively).

If a match is found, well, then we know it is a Wiimote. Open a Win32 file handle to the device using the device path fetched with SetupDiGetDeviceInterfaceDetail. The file handle itself is created using the standard CreateFile API.

Now that we have a file handle, I/O can be performed using simple ReadFile and WriteFile calls (synchronously or otherwise).

Unfortunately, sometimes, the Wiimote does not seem to respond to WriteFile calls. Brian must have been getting uncertain results with this which would explain why he put in a secondary I/O mechanism in case WriteFile is not working. The secondary mechanism to simply use the HID HidD_SetOutputReport API to send data to the Wiimote.

I wanted to stick to the same I/O mechanism in general. Being a driver however, things work a little differently (the fact that this is running in user mode does not seem to matter - it still is a driver and has some of the same functional constraints as kernel mode drivers). Consider the following line from the file "WiimoteSensor.inx" (this file is used as the template for generating the "WiimoteSensor.inf" file during the build process - "WiimoteSensor.inf" contains the installation instructions used by Windows when the driver is installed):

This line basically associates this driver with a specific hardware device. The string HID\{000... indicates that this driver talks to a HID device and the stuff after the \ is used to identify the particular HID device that this driver is built for. This sub-string can be considered as being delimited with _ characters with the first token being a GUID - {00001124-0000-1000-8000-00805f9b34fb} - that specifies that this is a Bluetooth HID device. The second token - VID&0002057e - specifies the vendor ID of the device and the third token - PID&0306 - specifies the product ID. This information is used by the device installer component of the OS to stack the correct lower level driver below the sensor driver. In our case, this would have to be the Bluetooth HID driver.

When an application issues an I/O request to a device, the request is usually made under the context of file handle that the application had previously opened. The device driver, UMDF or otherwise, has access to the file handle if it needs to. Now, in case a UMDF driver needs to issue a new I/O request to the next driver stacked below it - separate from anything that a client application might have done - then it is expected to use the IWDFDevice::CreateWdfFile method to first obtain a pointer to an object implementing IWDFDriverCreatedFile and then use that pointer like a file handle to refer to the device to which the I/O must be directed. The handle is to be used in conjunction with an IWDFIoTarget object which represents the lower level driver stacked below the UMDF driver. Issuing an asynchronous read request for instance is performed like so:

Call IWDFDevice::CreateRequest to create an IWDFIoRequest object.

Call IWDFIoRequest::SetCompletionCallback to supply a callback object that implements IRequestCallbackRequestCompletion so it can be notified of it when the I/O operation completes.

Call IWDFDevice::GetDefaultIoTarget to obtain a reference to the IWDFIoTarget object.

Use IWDFDevice::CreatePreallocatedWdfMemory and IWDFIoTarget::FormatRequestForRead to setup the memory buffers that will be used during the I/O.

Call IWDFIoRequest::Send to actually issue the request.

In the Wiimote driver, this whole process is initiated from CAccelerometerSensor::StartIO. The core logic for performing the I/O is implemented in the CReadWriteRequest class.

The CAccelerometerSensor::StartIO method also tries to read the calibration data for the accelerometer from a pre-defined memory location on the Wiimote. Just like the WiimoteLib, the driver first attempts this by issuing a "read memory" request using CReadWriteRequest::CreateAndSendWriteRequest. If that times out, i.e. a response is not received in a reasonable time-frame then it uses an alternate method by sending the IOCTL_HID_SET_OUTPUT_REPORT IOCTL to the HID driver. It accomplishes this by calling CReadWriteRequest::CreateAndSendIOCTLRequest.

The code in the Wiimote sensor driver can be used as a template for implementing your own sensor drivers. The key class to pay attention to is the CSensor class. Implementing a new sensor should essentially involve defining a new class that inherits from CSensor and overrides the relevant methods. This allows the driver writer to focus on the implementation of the core functionality instead of the plumbing required to interact with the sensor platform and UMDF.

============================
Btw, in the Pairing your Wiimote with your computer step 7, I failed to run "WiimoteTest.exe". It shows "No Wiimotes found in HID device list"http://i.imgur.com/EWOzL.png[^]

C:\Wiisensor\amd64\tools\devcon\amd64>devcon.exe install wiimoteSensor.inf"HID\{
00001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306"
devcon.exe: Invalid use of install.
For more information, type: devcon.exe help install

C:\Wiisensor\amd64\tools\devcon\amd64>
C:\Wiisensor\amd64\tools\devcon\amd64>devcon.exe install wiimoteSensor.inf "HID\
{00001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306"
devcon.exe failed. (I tried putting a space between the ending of .inf and the quote that begins the string line)

I have seen the post of one other person using 32bit system that got the issue resolved but I am using 64 bits. I have the quotes as you suggested. I am no coder but I understand a little. Thanks again

Assuming you ran the command all on one line, your second example is the correct one. There needs to be a space character before the "HID..." bit. Do you think you can locate a file called "setupapi.dev.log" from C:\Windows\INF and mail it to me at avranju@gmail.com? Thanks.

Thanks for sending the file. I don't see anything in there about installing the Wii sensor driver. Actually, after reading your original post a bit more carefully I see that you seem to be running devcon from within the C:\Wiisensor\amd64\tools\devcon\amd64 folder. That won't work because when you supply the name of the INF file, "devcon" is going to look for it in the current folder where it wouldn't find it. Please set the current directory in your command prompt to C:\Wiisensor\amd64 and run all of the following exactly as given below on a single line:

Hi Rajasenkharan, I followed the instructions and I paste this line in the cmd (my windows is 7 64 bits):
C:\Wiisensor\amd64\tools\devcon\amd64\devcon.exe install WiimoteSensor.inf "HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306"

I can successfully follow all the steps in the article. I can calibrate the 4 edge points but that's it. The Wiimote whiteboard box comes back, it has 55% tracking util, there is 1 visible IR dot when I touch the screen with the pen but there is no mouse emulation. Win7, 8G, HP I7.
Can anybody help? Mike

Hi, first thank for your very detail article. Thought it did not work for me ( cause I'm using a suck device called Dell bluetooth 365 module ).

I tried about 4 or 5 times, it didn't go anywhere so I decided to uninstall the driver. When I try to delete the key {00001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306 under HKLM\System\CurrentControlSet\Enum\HID, it keep display error [ Cannot delete ......: Error while deleting key... ], what should I do ? Notice that I had full control over the win7 ( event Ower right \ Permission of that key ).

Sorry to hear that your bluetooth stack is not playing nice. Is the Wiimote failing to pair completely? Are you able to use WiimoteTest.exe successfully?

To remove the driver, please try the following command from an elevated command prompt from the appropriate tools\devcon\<platform> folder where <platform> is "i386" if you are running the 32-bit version of Windows 7 and "amd64" if you are running the 64-bit version:

I don't think you need to delete that key from the registry. That path sounds like it is the entry for the Wiimote bluetooth HID device. You should probably try removing the device via "Device Manager". Look for the device in the device tree in "Device Manager" and right click on it and select "Uninsntall". You can quickly launch "Device Manager" by clicking Start/Run and typing "devmgmt.msc".

If "WiimoteTest.exe" is not able to communicate with the Wiimote then chances are there is some pairing issue. I suggest you google[^] it up and see how it can be resolved for the specific hardware that you have.

As for the installation issue, please do it exactly the way it is given in the article. For example, on a 32-bit system, navigate to C:\Wiisensor\i386 in a command prompt and run all of the following on a single line:

every step is ok until "Taking her out for a ride". wiidiag or demo app just crash after launching without any error message.

i have this message in the device manager, "this device can't start (code 10)". I suppose that something went wrong during driver install or else, but i don't see what. No way to make this message disappear.

If the device is not starting it could be because of one of the following:

Wiimote did not pair with the system correctly - make sure that you are able to use Brian Peek's Wiimote test app just fine before attempting to install the sensor driver.

The driver did not install properly. Try removing the sensor device and the wiimote controller from the bluetooth console and then pair and install driver again.

Here's what Microsoft has to say about this error code on their support[^] site:

Microsoft support:

To resolve this error code, make sure the device is connected to the computer correctly. For example, make sure all cables are plugged in fully and that all adapter cards are properly seated. Follow the suggested solution button and update the device driver. It may be possible to remove the device and redetect it using the Add New Hardware wizard.

you're right, wimotetest does not run correctly, buttons works fine but not the pointer. it's the same with glovepie. I give up. no way to detect wiimote movement. I can't find any error message.I used blue soleil to pair the wiimote or directly windows seven blutooth manager, the behavior of the wiimote is always the same, buttons works but not the movement.

Me too. Wiimote is connected, work with WiiTest but also apps like WiiRemote and Dolphin. But in location sensors it states as not connected+in devicemanager states error code 10: device cannot start.
Btw with devcon install of wiimotesensor, only one wiimote came up in device manager instead of two. So I geuss the only one came up was the one the guide said to remove lol.

C:\Wiisensor\i386\tools\devcon\i386>devcon.exe install WiimoteSensor.inf HID\{00
001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306
Device node created. Install is complete when drivers are installed...
Updating drivers for HID\{00001124-0000-1000-8000-00805f9b34fb}_VID from C:\Wiis
ensor\i386\tools\devcon\i386\WiimoteSensor.inf.
devcon.exe failed.
'0002057e_PID' is not recognized as an internal or external command,
operable program or batch file.
'0306' is not recognized as an internal or external command,
operable program or batch file.

C:\Wiisensor\i386\tools\devcon\i386>devcon.exe install WiimoteSensor.inf
devcon.exe: Invalid use of install.
For more information, type: devcon.exe help install

C:\Wiisensor\i386\tools\devcon\i386>devcon.exe install WiimoteSensor.inf HID\{00
001124-0000-1000-8000-00805f9b34fb}_VID&0002057e_PID&0306
Device node created. Install is complete when drivers are installed...
Updating drivers for HID\{00001124-0000-1000-8000-00805f9b34fb}_VID from C:\Wiis
ensor\i386\tools\devcon\i386\WiimoteSensor.inf.
devcon.exe failed.
'0002057e_PID' is not recognized as an internal or external command,
operable program or batch file.
'0306' is not recognized as an internal or external command,
operable program or batch file.

I have followed all steps that you described in your article. For your information I use 32 bit Windows 7 OS and install driver located in i386 folder.

Also I have tried WiimoteTest.exe to test pairing between bluetooth and Wiimote just after pairing done between bluetooth and wiimote. When i run an application it displays error message with information: "Timed out waiting for status report" and with heading "Microsoft .Net Framework". Dialogbox has option to countinue or quit. If i continue then WiimoteTest application appear and it works fine.

After that, When i starts Wiidiag application, it runs fine but data are not received or shown in an application. Same thing happens with PlaneDemo application. Also some times it show an error message when i start an application.

If i run WiimoteTest application after this, then it shows error message: "No wiimotes found in HID device list".

Please give your suggestion on this or point out when actually problem occurs.

Did the Wiimote driver installation succeed? When you run "Wiidiag", what does it say in the "Sensor State" field? Whenever something goes wrong you usually have to completely delete the device from the "bluetooth devices" console and pair again. The pairing experience for the Wiimote is a real pain-point at this time. Getting past that can be a little challenging as you probably can tell by looking at the other posts here.

Installation of driver was successfully done and in wiidiag application "Sensor State" field shows "Ready" state.

As per your suggestion, i have removed all the things (wiimote from bluetooth device and uninstall driver, etc) and again pair wiimote with blue tooth devices and install driver several times but i can not get success.

Same thing happen when i execute Plane Demo application. This application starts well but it does not show any update or show values of axes in textblock.

To send data from wiimote, is there any single button or combination of buttons needed to press on wiimote or data automatically passed to application?

If you're sure its 64-bit Windows then I can only suspect that your download has somehow become corrupt. Does the 32-bit version of devcon.exe run? It won't be able to install the driver but you should get some kind of error that makes sense. You might want to try downloading the zip file afresh or if you have the DDK installed then try to use the version of "devcon.exe" that comes with it.

I have the device added through Bluetooth and installed with the drivers (although it says "Wiimote Sensor" under Sensors. None of the utilities are able to read the data from it. Wiidiag says "AccessDenied" and WiimoteTest says "No Wiimotes found in HID device list." I did see that the Vendor ID is actually 2057e, not 057e as the article states. I'm runing 64-bit Win7. Any thoughts?

If "Wiidiag" says "AccessDenied" then it is probably because you haven't enabled the sensor in the "Sensor and Location" control panel. Please see step 7 in the section called Installing the driver[^]. Hope this helps!

When it didn't work the first time I removed it and reinstalled it. You are right that I forgot to enable the sensor the second time. I'm back to what prompted me to reinstall! Wiidiag says "ready" but shows no activity for any axis. Plane app also looks fine but reflects no sensor data. Peek's WiimoteTest app still says "No Wiimotes found in HID device list." Any other thoughts of what I can do?

Hmm. Can you try removing everything and then pair the Wiimote back with the system and just run WiimoteTest.exe? I want to rule out the possibility that the bluetooth stack on your machine is failing to pair with the Wiimote correctly. If it pairs correctly then WiimoteTest.exe should be able to communicate with it.

I did this and WiimoteTest looks great. I can view/set all information right after pairing. Then I installed the driver from the command line and this time it works. Third time's a charm. Weird. I'm not sure what happened, but it works now. Oh well! Thanks for posting this very informative article.