So, when I started working on the documentation for the sensor platform, I started at the bottom: the driver level. I've been at Microsoft 8 years now. In fact, my anniversary was this week. Come to think of it, my wedding anniversary was this week, too. That makes it easier to remember both dates, I guess. Anyway, in 8 years at Microsoft, I never got involved in drivers, until now. All of my work has been at the API level. Maybe I'm weird, but I was pretty excited to get to work on some driver code. But I'll admit, I was a bit intimidated at the thought, too.
Fortunately, the development team had already written a skeleton sample driver, so that helped. It also helped that sensor drivers use the User Mode Driver Framework (UMDF), which means that writing driver code is a very similar process to writing application code using COM. And what helped even more was that the development team had the foresight to create the sensor class extension.
The class extension is simply a COM object that handles managing the connection between the driver and the sensor platform. The UMDF driver simply CoCreates the class extension, calls QueryInterface for ISensorClassExtension, and then calls Initialize to provide a couple of IUnknown pointers: one points to the driver class and one points to a callback interface, ISensorDriver. The beauty of the class extension is that these two interfaces manage the entire connection. When a driver makes calls to the sensor platform, it uses ISensorClassExtension. When the platform makes calls to the driver, it uses ISensorDriver. That's it. Simple is beautiful.
Now, I wanted my first foray into sensor drivers to be as simple as possible (did I mention I like simplicity?), so I set a couple of criteria for my first driver. First, I decided it shouldn't require any actual hardware. That way, I could eliminate a whole mess of code to connect to a hardware device. I just wanted to concentrate on how the sensor driver model works. This would also make my sensor an ideal candidate to learn how logical (virtual, software-based) sensors work. Second, I decided to remove as much code from the skeleton driver as possible. This meant I would remove one of the classes so that I could implement the ISensorDriver methods right in the callback method blocks, instead of calling through to another class.
I thought for a bit about what kind of sensor my driver should be. Again, seeking simplicity (I'm a simple guy), I thought it would be best if the sensor just served up some data from the Windows system. I looked a bit at the Windows instrumentation APIs and thought perhaps my sensor could report data about processor speed, or something like that. I wanted to make a driver that defined a custom sensor category, type, and data types, too. See, part of my job is to learn about all the aspects of the platform, so I try to be efficient about that. Then, it hit me. The very simplest thing to do would be to simply call ::GetLocalTime and then break the time down into three data fields: hour, minute, and second! My "time sensor" fit all my criteria: simple, logical, and custom.
If you spend some time using the WDK documentation (after we release the beta), you'll see vestiges of this time sensor code in the documentation examples. At some point, I'll find a way to release the whole driver as a sample, too.
So I set to work creating my time driver. I still had a few things to learn about UMDF drivers. Like how to install them for testing (you use devcon.exe), how to uninstall them (you use Device Manager to uninstall and check the delete files checkbox), what a device node is (it's the object that gets created when the driver shows up in Device Manager), and which interfaces and method calls you use to manage lifetime (like this and this).
But my time driver works great, now. I use the Sensor API to receive an event every second to update the time in my application. Maybe that seems like a long way to go to get a clock, but I can imagine real-world applications for a time sensor. How about a sensor that gets the current time via radio from the USNO Atomic Clock? Or from a Web service? Or via satellite?
But more importantly, I learned what I needed to learn about sensor drivers. And I'll be sharing that knowledge, here, and in the official documentation.