A few devices, like mice and keyboards, are intended to be read directly by the operating system. These few special devices cannot in fact be opened for direct I/O by a user mode Windows program.
Most other devices need some kind of a program to talk to control them, send commands to them, and receive and display data from them. Most users expect a real Windows GUI program with products that they buy.
A Windows program that you write yourself does not talk directly to your HID device, but instead must work through a sequence of rather obscure and confusing Windows API calls. These API calls ultimately communicate with the HID and USB device drivers that are built into the operating system.
These API calls are very low level, often requiring that you first set up complicated data structures and fill in these, in just the right way, before you can call the API function.
Working with this very old-fashioned API approach is time consuming and error prone, and requires deep knowledge of the PC operating system. (For most people, that's Microsoft Windows.)
On the plus side, at least the PC operating system provides a considerable amount of intelligence that knows how to work with the USB bus, find devices that are connected to it, and pack and unpack the data from HID class Input, Output, and Feature Reports.
Also, the video display, keyboard, and mouse of the PC provide the ability to develop and debug the program right on the PC. The large amount of memory of a modern PC makes it possible to have friendly development and debugging software and modern object-oriented programming languages that are relatively easy to read and maintain.
What about the software ("firmware") on the peripheral device?
Working with a microcontroller-based USB peripheral device is harder than working on a PC program, partly because there is no operating system on the microcontroller at all.
Another reason that it is harder is that memory is more limited on the peripheral device, and there isn't always screen and keyboard to help you see what is going on.
Software for the peripheral device has to do the usual stuff that any microcontroller software must do, like declare all the variables, initialize all the hardware, and set up a main loop that performs whatever work the device must do.
In addition, it has to have extra USB stuff in it as well, such as the complicated USB descriptor tables, code to initialize and start up the USB engine, code to run the USB engine, and of course, code to pack the data into packets that are going IN to the PC, and unpack any data that comes OUT from the PC.
The microcontroller code has to do everything, because there is no operating system like Windows there to do any of the work for us.
Debugging a regular microcontroller project that runs by itself is hard enough. The micro doesn't have a display or keyboard or mouse to help us see what is happening and control it directly.
That's why we need special debugging hardware tools such as In Circuit Debuggers and Emulators. (Sometimes, like when we have a brand new printed circuit board design, we can't even be sure that the hardware itself is working properly.)
Debugging a USB microcontroller project is harder still, because we now have a two processor system: our peripheral's micro, and that other processor on the other side of the USB cable, the PC. If we set a breakpoint in the microcontroller code, the PC immediately decides that our device has died, and disables the USB connection to it.
For most of us, we start a project like this with a pretty good idea of what the peripheral device must do, what the PC should do and display, and what sort of data needs to flow between the two in order to make all that happen.
It sure would be nice if there were some way we could just magically get:
- a matched set of "known good" PC side and peripheral side programs,
- that can reliably send and receive the specific data that we want, and
- if we could have these programs written for us in our favorite programming languages.
Well, there IS a way. It's called HIDmaker FS.