I found an Intel Qx3 Play camera at Goodwill for $0.99. I've wanted a microscope for the lab, and it's cheap! How could I say no? :)
Unfortunately Intel has chosen not to make modern drivers for this 13 year old kit. That's unfortunate, but I don't blame them. To get it to work with their software I have to go all the way back to Windows Me or Windows 2000. That isn't going to happen. This thing is so old that they don't even have it on their website anymore. I would have to download it from cNet.
There is some good news. The unit works with Linux. I fired up an Ubuntu Live CD and verified that it works. Yeah! Unfortunately I can't use a Hyper-V VM and Ubuntu because USB passthrough only works with Windows Server 2012 and Windows 8 guest operating systems. :/
So that sucks.
Fine. I'll try to get it working in Windows instead. How hard could it be to write a USB device driver? It's simple Algebra.
Negative - I haven't programmed in C since puberty.
Negative - I've never written a Windows driver before.
Negative x Negative = I'm POSITIVE I can do this.
This is the perfect combination of hubris and obsession for this to be an awesome project.
So I got the chip specifications and developer's guide from this page: http://webcam.sourceforge.net
Ironically, that is where the Linux developers parked their stuff when they wrote this driver for Linux.
Next up I read the developer documentation on the slashdot site and started slogging through the writing a driver documentation on MSDN. I also grabbed a copy of "Developing Drivers with the Windows Driver Foundation". That's a link to Amazon, but I actually read it on Safari. It's a little light bedtime reading.
One of the first steps is choosing a driver model: MSDN: Choose a model for developing a USB client driver. From the chip documentation I learned that I need one control endpoint and one isosynchronous endpoint. That narrows down my choices significantly.
I had hoped to make it work with the baked-in Windows USB Video Driver module by writing an extension to usbvideo.sys but that won't work. The camera either supports that or it doesn't.
The remaining options are writing a Kernel Mode Driver (hard) or using the generic WinUSB driver and building all of the intelligence into the application. For now I've chosen the latter, as it is a much simpler solution. The unfortunate bit is that this driver will only work in Windows 8.1. It is the only OS that supports isosynchronous data transfers with winusb.
Fast forward 48 hours. I've installed Visual Studio 2013, Update 3, and the Windows Driver Framework for Windows 8. (This takes forever. :D )(Seriously, you can take a nap.) I used the Visual Studio WinUSB template to kick out the .inf for the driver and a stub application. This MSDN tutorial is incredibly helpful: Write a Windows desktop app based on the WinUSB template. Yesterday I got a stub application working which can identify when the device is plugged in and read the firmware version from it. Today I moved all of the device specific code into its own class and started cranking out all of the functions needed to make to work. It's just after midnight and I have 70% of the API written for the Control Channel.
With any luck I'll get the isosynchronous endpoint communication working tomorrow and get some data to play with. My plan is to release the source code, driver, and completed application as open source. This is awesome!
Useful things I've learned so far.
Windows 8.1 will not permit you to install an unsigned driver by default.
- The workaround is to reboot with "shutdown -r -o -f -t 15" and select the advanced mode that will allow you to install the driver.
The security of the sprintf command has been tightened down significantly.
- I had to switch to using sprintf_s to get past a fatal compiler warning.
Time for bed before I become more hallucinogenic/delusional from sleep deprivation.