Part 2: HID USB Mouse

That covers about half of USB HID library, how about we add a mouse to the mix now? Implementing a USB HID mouse requires a few more functions, but it's still crazy simple. There are five functions provided by Arduino's HID class that can be used to implement a mouse:

  • Mouse.move(x, y, wheel) - This function tells the computer to move the mouse a certain number of pixels along either the x, y and/or wheel axis. Each variable can be any value between -128 and +127, with negative numbers moving the cursor down/left, positive numbers move the right/up.
  • Mouse.press(b) - This function sends a down-click on button(s) (one or more) b. The button(s) will remain 'pressed' until you call Mouse.release(b). The b variable is a single byte, each bit of which represents a different button. You can set it equal to any of the following, or OR them together to click multiple buttons at once:
    • MOUSE_LEFT - Left Mouse button
    • MOUSE_RIGHT - Right Mouse button
    • MOUSE_MIDDLE - Middle mouse button
    • MOUSE_ALL - All three mouse buttons
  • Mouse.release(b) - Similar to Mouse.press(b), this function sends an up-click signal to the computer to tell it that a button has been released.
  • Mouse.click(b) - This function sends a down-click (press) followed immediately by an up-click (release) on button(s) b.
Ever want to control your computer's cursor with a joystick? Well, you may not want to after this example (it's not exactly precise), but at least it'll show you how to use the Mouse class. For those playing along, I'm using our Thumb Joystick, planted into its breakout, and connected to the Pro Micro.
The joystick is powered by the Pro Micro's VCC and GND pins. The horizontal analog output is connected to A0, vertical to A1, and the select switch is connected to D9. As always, feel free to hook it up however you want, just make sure to change the pin definitions near the top of the code.
Here's the code:
The loop() of this code continuously monitors the horizontal and vertical analog values of the joystick, and sends the Mouse.move() command based on what it reads. It'll move the mouse in steps, depending on what the sensitivity variable is set to. With sensitivity set to 2, the cursor will move in either 1 or 2 pixel steps.
It's important to note that the variables used by Mouse.move() -vertValue and horzValue - can be either negative or positive; their sign determines whether the mouse moves up/down or left/right.
The select switch on the joystick is used to control the mouse left click. Notice this code is using Mouse.press() and Mouse.release(), rather than just calling a single Mouse.click(). This requires a bit more coding, but it allows you to do things like drag-and-drop, double click, etc.

Part 3: Keyboard Modifiers and Non-ASCII Characters

Note (June 26, 2012): With the officical release of Leonardo in Arduino 1.0.1, a lot has changed for the better in the core USB and HID files. You can now send keyboard modifiers and non-ASCII characters using the Keyboard Write, Press, and Release member functions detailed in Part 1 above. The following defines were added to Arduino:
So, if you wanted to be evil and send ALT+F4, you could write something like:
Remember that write sends both a press and release. If you use just the press function, make sure you release the button shortly afterwards (unless evil really is your goal).
And it's become that easy! If you haven't upgraded to Arduino 1.0 yet, the below information will still apply. So, I'll keep it as is for now.
End Note (June 26, 2012)
So, that's the sum of what's provided for in the Arduino 1.0 HID library. Enough to emulate just about every mouse and keyboard action there is. However, if you're like me, you may be left wanting a little bit more. For instance, what if you want to send non-ASCII-standard keys to your computer, like the function keys, arrow keys, or even modifiers like CTRL, ALT and SHIFT? The HID library doesn't really support those by default, but we can fix that...
I'll preface this section by saying we're going to be doing a little code hacking within Arduino's core libraries. It's nothing that should cause any problems to your Arduino install -- really just one very minor change -- but you will need to be careful about how you use the code in this section.
Using a programmingtext editor, you'll need to open up USBAPI.h, in the hardwarearduinocoresarduinodirectory of your Arduino install. Any text editor will do, but it's best to use a code editor (Notepad++ or Programmer's Notepad are good ones).

The Keyboard class definition starts at line 96, and should look like this:

To send special characters and modifiers, we need to use the void sendReport(KeyReport) member function. Unfortunately, that function is currently listed under the private: label, which means we can't access it in our Arduino sketch. To make it usable, though, all you need to do is move it under the public: label. So, cut the entire void sendReport(keyReport* keys) line and paste it just under the public: line. In the end your Keyboard class prototype should look something like this:

Remember to save the header file, and close it. That's all the code hacking you have to do!
To use Keyboard.sendReport() you'll need to give it a KeyReport, which is a data structure (here's a good read for those unfamiliar) defined in USBAPI.h. Here's how it's defined:
A KeyReport contains information like what keys are pressed, and if there are any keys (SHIFT, CTRL, ALT, GUI) modifying it. Each KeyReport has three member variables: keys[6], modifiers, and reserved. We won't make any use of reserved, but the other two are important.
The keys[6] array can store up to six key presses at any one time. For the most part the first value of the array, keys[0], is all you need. The actual value assigned to this variable is not ASCII though, it's is an HID usage ID. The USB standard assigns specific IDs for each and every button on a keyboard; they're all listed in this official HID Usage Table document (the table starts on page 53). Click the image below to see a HUGE listing of all the defined HID Keyboard Usages (your browser should allow you to zoom in on the image):
Basically, what this all means is you can't set keys[0] to the character 'A,' because the ASCII value of 'A' (0x41) is not the same as the usage value of 'A' (0x04).
The modifiers variable controls which, if any, modifiers are acting on a key press. You can set modifiers equal to any of the following macros:
You can also OR (|) any of those macros together to specify multiple modifiers at the same time.
Once we have all the values we need set up in a keyReport, we can finally send it over to the sendReport(keyReport) function, which will report all keys and modifiers to the computer.
Clear as mud? Let's just jump into the code.

This example uses the hardware setup in the very first bit of code -- a single button attached to pin 9.

This time, I've added a new function -- sendKey(byte key, byte modifiers) -- which can be passed to both a key (an HID usage ID) and modifiers. It'll take care of setting up the KeyReport variable, and sending all the necessary reports.

It shouldn't take much to guess what's being passed to the sendKey() function in that example. It's the three-finger salute, CTRL+ALT+DEL. Windows users should be familiar with CTRL+ALT+DEL; for them, grounding pin 9 should either call the task manager, or open the Windows Security dialog.

Mac/Linux people, I'm not sure if that'll do anything for you. If you'd rather not have a CTRL+ALT+DEL key, you can replace the modifier parameters with KEY_MODIFIER_LEFT_CTRL (or KEY_MODIFIER_LEFT_GUI for Macs), and the key value with 0x06 (the [C] key usage id). Now you've got a button devoted to copying, and it shouldn't take much more to add a paste key.

Look closely at the sendKey() function. Notice that we have to send two different HID reports. The first report sends our key, and any modifiers that may be included. The second report sends a completely blanked out KeyReport, which is necessary to tell the computer that the key has been released. This is probably why Arduino kept sendReport() as a private function, it's got a lot of mess-making potential if used incorrectly. Be careful!

You'll notice that KEY_DELETE is defined as 0x4C, which matches the 'Usage ID (Hex)' value of 'Keyboard Delete Forward' in that HID Usage Table document I linked above. Use that as an example for any other keys you'd like to use. There's some intriguing keys defined in there...F24 (0x73)? Who knew it went that high? Volume Up/Volume Down (0x80, 0x81)? Media player controller? RightArrow, LeftArrow, DownArrow, and UpArrow (0x4F-0x52) could be very useful!

If you want to spend a bit less time digging through that table, feel free to adapt this example code, which also includes a header file (HID_Keyboard_Advanced.h) with all of the usage ID's defined.

You can now create any type of USB input device you could ever dream of. Want to use an old arcade joystick as you play an online arcade game? Make one! Here's some code to get you started. You can use the joystick hardware setup from the mouse example above. That code will use the advanced keystrokes, replacing mouse control with up, down, left and right arrow keystrokes.

Conclusion

Well, that was a long-winded tutorial, but this subject has me really excited; I can't help but talk about it! I think the simplicity of Arduino's HID classes opens up an immense world of physical computing possibilities. I'm excited to see what kind of crazy USB devices you all come up with.
I hope this tutorial has you as excited about Arduino USB HID stuff as me. If you've got any questions, or need something clarified, please post in the comments below.
Thanks for taking the time to check this tutorial out!