Monday, 25 May 2020

USB HID Keyboard

http://mitchtech.net/arduino-usb-hid-keyboard/

Arduino USB HID Keyboard

Turn your Arduino UNO into a USB HID keyboard, and make buttons that do whatever you want. Make it a useful tool, with new buttons for Cut/Copy/Paste or Volume+/Volume-/Mute, or annoy your friends and colleagues by setting the keyboard to perform random keypress after random delays!
The USB HID keyboard conforms to the standard USB specification, so is functional on all modern operating systems.  All this is made possible by the use of the Arduino Device Firmware Update (DFU) function.

Arduino Device Firmware Update (DFU)

The Atmega8U2 chip on the Arduino UNO can be programmed directly using the special USB protocol called Device Firmware Update (DFU). This is completely independant of the ‘normal’ method of flashing sketches to the board using the Arduino IDE.
This process is normally used to update the firmware to a more recent version, as explained in the offical Arduino guide, Updating the Atmega8U2 on an Uno or Mega2560 using DFU. Note: If your board is NOT an Arduino UNO SMD you’ll need to solder a 10k resistor (Brown-black-orange) at the back of your board as shown on the Arduino site.
However, in addition to the ability to flash standard USB Serial firmwares, we can also flash alternative firmwares as well. This allows the device to be recognized as many other device types, including keyboard, mouse, joystick, midi device, etc. This is made possible in part to the wonderful open source LUFA (Lightweight USB Framework for AVRs)  USB stack, and keyboard HID firmware from Darran.
In this demonstration, we will flash generic USB HID keyboard firmware. The USB HID protocol provides manufactures the generic specifications to interact with nearly every operating system in existence. For more info, check out the USB HID Spec sheet.
Before you start, install the required packages. On Ubuntu and Debain systems, in a terminal run:
sudo apt-get install dfu-programmer dfu-util
For Windows and Mac instructions to install the dfu-programmer tool, consult the official Arduino DFU documentation.
Then download these two firmware files:
The first step is to make sure you are able to flash the standard arduino firmware. This will confirm that the programmer and the environment are both functional. NOTE: There is no chance of ‘bricking’ the device using this method. The Arduino bootloader firmware can always be updated using the DFU protocol!
sudo dfu-programmer at90usb82 erase
sudo dfu-programmer at90usb82 flash --debug 1 Arduino-usbserial.hex
sudo dfu-programmer at90usb82 reset
Plug cycle the Arduino, then open the Arduino IDE and ensure that you can still upload a sketch. Assuming everything flashes normally, we can move forward with flashing the HID keyboard firmware.
sudo dfu-programmer at90usb82 erase
sudo dfu-programmer at90usb82 flash --debug 1 Arduino-keyboard-0.3.hex
sudo dfu-programmer at90usb82 reset
NOTE: The Arduino can only be flashed with skectches through the Adruino IDE if the Arduino-usbserial.hex bootloader is active. So, to develop a USB HID device, the process becomes:
Flash Arduino-usbserial.hex bootloader with dfu-programmer (erase/flash/reset)
Plug cycle the Arduino
Flash firmware sketch using Arduino IDE
Plug cycle the Arduino
Flash Arduino-keyboard-0.3.hex bootloader with dfu-programmer (erase/flash/reset)
Test and repeat
Now that you understand how the process works, you can try out some of these keyboard samples. The easiest example is the random keypress with random delays, since it doesn’t require any components connected to the Arduino.

Random Key/Random Delay

/* Arduino USB HID Keyboard Demo
* Random Key/Random Delay
*/
uint8_t buf[8] = {
0 }; /* Keyboard report buffer */
void setup()
{
Serial.begin(9600);
randomSeed(analogRead(0));
delay(200);
}
void loop()
{
int randomChar = random(4, 130);
long randomDelay = random(1000, 10000);
delay(randomDelay);
buf[2] = randomChar; // Random character
Serial.write(buf, 8); // Send keypress
releaseKey();
}
void releaseKey()
{
buf[0] = 0;
buf[2] = 0;
Serial.write(buf, 8); // Release key
}
view rawUSB_HID_Random.ino hosted with ❤ by GitHub
The following two examples both use three buttons connected to the Arduino. The code can easily be changed to make the buttons perform other actions, by consulting the mapping tables in the USB HID documentation.  Here is a diagram of the circuit, (created with Fritzing):

Volume+/Volume-/Mute

/* Arduino USB Keyboard HID demo
* Volume+/Volume-/Mute keys
*/
uint8_t buf[8] = {
0 }; /* Keyboard report buffer */
#define PIN_VOLUME_UP 5
#define PIN_VOLUME_DOWN 6
#define PIN_MUTE 7
int state = 1;
void setup()
{
Serial.begin(9600);
pinMode(PIN_VOLUME_UP, INPUT);
pinMode(PIN_VOLUME_DOWN, INPUT);
pinMode(PIN_MUTE, INPUT);
// enable internal pull-ups
digitalWrite(PIN_VOLUME_UP, 1);
digitalWrite(PIN_VOLUME_DOWN, 1);
digitalWrite(PIN_MUTE, 1);
delay(200);
}
void loop()
{
state = digitalRead(PIN_VOLUME_UP);
if (state != 1) {
buf[2] = 128; // Volume up key
Serial.write(buf, 8); // Send keypress
releaseKey();
}
state = digitalRead(PIN_VOLUME_DOWN);
if (state != 1) {
buf[2] = 129; // Volume down key
Serial.write(buf, 8); // Send keypress
releaseKey();
}
state = digitalRead(PIN_MUTE);
if (state != 1) {
buf[2] = 127; // Mute key
Serial.write(buf, 8); // Send keypress
releaseKey();
}
}
void releaseKey()
{
buf[0] = 0;
buf[2] = 0;
Serial.write(buf, 8); // Release key
}
view rawUSB_HID_Volume.ino hosted with ❤ by GitHub

Cut/Copy/Paste

/* Arduino USB Keyboard HID demo
* Cut/Copy/Paste Keys
*/
#define KEY_LEFT_CTRL 0x01
#define KEY_LEFT_SHIFT 0x02
#define KEY_RIGHT_CTRL 0x10
#define KEY_RIGHT_SHIFT 0x20
uint8_t buf[8] = {
0 }; /* Keyboard report buffer */
#define PIN_COPY 5
#define PIN_CUT 6
#define PIN_PASTE 7
int state = 1;
void setup()
{
Serial.begin(9600);
pinMode(PIN_COPY, INPUT);
pinMode(PIN_CUT, INPUT);
pinMode(PIN_PASTE, INPUT);
// Enable internal pull-ups
digitalWrite(PIN_COPY, 1);
digitalWrite(PIN_CUT, 1);
digitalWrite(PIN_PASTE, 1);
delay(200);
}
void loop()
{
state = digitalRead(PIN_CUT);
if (state != 1) {
buf[0] = KEY_LEFT_CTRL; // Ctrl
buf[2] = 27; // Letter X
// buf[2] = 123; // Cut key: Less portable
Serial.write(buf, 8); // Ssend keypress
releaseKey();
}
state = digitalRead(PIN_COPY);
if (state != 1) {
buf[0] = KEY_LEFT_CTRL; // Ctrl
buf[2] = 6; // Letter C
// buf[2] = 124; // Copy key: Less portable
Serial.write(buf, 8); // Send keypress
releaseKey();
}
state = digitalRead(PIN_PASTE);
if (state != 1) {
buf[0] = KEY_LEFT_CTRL; // Ctrl
buf[2] = 25; // Letter V
// buf[2] = 125; // Paste key: Less portable
Serial.write(buf, 8); // Send keypress
releaseKey();
}
}
void releaseKey()
{
buf[0] = 0;
buf[2] = 0;
Serial.write(buf, 8); // Release key
delay(500);
}

No comments:

Post a Comment