In this article I will walk through how to set up an Arduino Leonardo as a mouse proxy using a USB Host Shield. By the end you should be able to plug your mouse into the shield on the Arduino, and use your mouse like normal on your computer.
Requirements#
- 1x Arudino Leonardo
- 1x USB Host Shield
- 1x Micro USB cable for the Arduino (MUST be a data cable and not just a charging cable)
- 1x Computer Mouse
The USB Host Shield I used was purchased from Tinkersphere. (Not sponsored)
Attach the Host Shield#
Attach the USB Host Shield to the Arduino Leonardo. Ensure the pins on the shield are lined up with the correct slots on the Leonardo.
Plug the Arduino into your computer#
Use your Micro-USB cable and plug the Leonardo into your computer.
If the Micro-USB cable you are using is just a charging cable, the Leonardo won’t be detected by your computer. You must use a cable that is capable of data transfer.
Install the USB Host Shield library#
First we need to ensure that the USB Host Shield library is installed.
Open Arduino IDE and at the top go to Tools > Manage Libraries
, or click the
icon at the left for the Library Manager
.
In the sidebar that shows up, search for USB Host Shield, and install the
USB Host Shield Library 2.0
.
The Code#
Thankfully, the USB Host Shield 2.0 library was kind enough to provide an example file – USBHIDBootMouse - that can easily be extended to accomplish our task.
#include <hidboot.h>
#include <usbhub.h>
#include <Mouse.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
// MouseRptParser extends the MouseReportParser and will use the Mouse.h library
// to perform the mouse action that is detected.
class MouseRptParser : public MouseReportParser {
protected:
void OnMouseMove (MOUSEINFO *mi);
void OnLeftButtonUp (MOUSEINFO *mi);
void OnLeftButtonDown (MOUSEINFO *mi);
void OnRightButtonUp (MOUSEINFO *mi);
void OnRightButtonDown (MOUSEINFO *mi);
void OnMiddleButtonUp (MOUSEINFO *mi);
void OnMiddleButtonDown (MOUSEINFO *mi);
};
void MouseRptParser::OnMouseMove(MOUSEINFO *mi) {
Serial.print("dx=");
Serial.print(mi->dX, DEC);
Serial.print(" dy=");
Serial.println(mi->dY, DEC);
Mouse.move(mi->dX, mi->dY);
};
void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) {
Serial.println("L Butt Up");
Mouse.release(MOUSE_LEFT);
};
void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) {
Serial.println("L Butt Dn");
Mouse.press(MOUSE_LEFT);
};
void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) {
Serial.println("R Butt Up");
Mouse.release(MOUSE_RIGHT);
};
void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) {
Serial.println("R Butt Dn");
Mouse.press(MOUSE_RIGHT);
};
void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) {
Serial.println("M Butt Up");
Mouse.release(MOUSE_MIDDLE);
};
void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) {
Serial.println("M Butt Dn");
Mouse.press(MOUSE_MIDDLE);
};
USB Usb;
USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE> HidMouse(&Usb);
MouseRptParser Prs;
void setup() {
Serial.begin( 115200 );
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
delay( 200 );
HidMouse.SetReportParser(0, &Prs);
Mouse.begin();
}
void loop() {
Usb.Task();
}
The only modifications that have been made was adding in the Mouse.h
library
to actually send the mouse actions to the computer, along with printing the
action to the serial monitor.
This doesn’t seem to work with all mice. I’ve noticed different behavior with different mice. Some didn’t work at all. Some would work, but in unexpected ways (clicking moves the mouse position instead of actually clicking).
I am using a G Pro Wireless X Superlight and it works perfect.
If your mouse doesn’t work, you may need to debug and print out what each mouse action is actually sending and adjust the MouseReportParser.
Upload the Code#
Once you have the code in the Arduino IDE, and the Arduino is plugged in with the shield attached, plug in your mouse to the shield and then upload the code.
Wait a few seconds, and once the code is uploaded you should see “start” printed to the serial console. Try moving your mouse and clicking on things. Everything should work perfectly as if your mouse is plugged into your computer, and you should see output in the serial monitor of the actions you are taking.
Note: Scroll is not implemented, so actions using the scroll wheel won’t work. This is left as an exercise for the reader.
Finished#
At this point you should have a fully functioning mouse proxy using the Arduino Leonardo and a USB Host Shield.
I see many people in the Arduino forums asking how to accomplish this so I figured I would write up a quick article. Overall the process was made extremely simple due to the provided example from the USB Host Shield 2.0 library.