Keyboard: individual press- and release-cmds

Using Arduino with the USBKeyboard.h and PluggableUSBHID.h libraries on an RP2040, I try to press and hold a key from the Keybaord.

I tried two ways

  1. using printf
  2. using key_code

Both work - but both only make a short key-stroke and release the key immediately. But what I need is to press-and-hold the key !!

How do I press and release a particular keyboard-Key with two individual commands ? (i.e. press vs. release) ?

I tried to run the Keyboard.h library - but it does not work on the RP2040 board.

Do you have an idea on how I can get keyboard key press and release on the RP2040 working ?

#include "PluggableUSBHID.h"
#include "USBKeyboard.h"

USBKeyboard Keyboard;

void setup() {

    // does press AND release at the same time
    // but I need two individual cmds, one for pess-key and one for release-key
    Keyboard.printf("a"); 

    // same here: does press AND release at the same time:
    // but I need individual press and individual release cmds
    Keyboard.key_code(DOWN_ARROW); 
}

void loop() { }

Try Keyboard.press('a'); and Keyboard.release('a');

This only works if you switch the Keyboard library (and by consequence potentially also the Arduino controller). The original libraries I used do not allow the "press" and "release" cmds separately (i.e. USBKeyboard.h and PluggableUSBHID.h do not allow that).

I figured a way to use "press" and "release" cmds with the library Keyboard.h (see documentation). This even worked on the QTPy RP2040 so I didn't even have to exchange the controller.

I've had this exact problem, and had to write my own solution. Unfortunately, I changed something which caused my changed files to be deleted. Luckily, I had one of them open, so I was able to copy and paste into a new file. That said, I still need to re-write the header file. I've posted my code below in sections for ease of viewing. The whole file is also added as an attachment to this post.

2 important things to note:

  • I was using an older mbed_os library, so your file may be slightly different
  • Note that I wanted to be able to press and send more than 6 keys (which is the default max); I'm using an array size of 10. So the comments in my code tend to that mention that (believe it or not, I write comments in my code even if I don't plan on sharing it). To increase the length of the report you'll need to modify line 407 or so (the first line of the section before Media Controls) to read:
        REPORT_COUNT(1), 0x0A,                  // Allows up to 10 keys.

The first problem is that the keyboard library doesn't allow multiple button presses to be sent in a report. This gives rise to the second problem: there's no press and release.

First we need to create an array to store the key values we want to send, I put this in the header file at the bottom, but I forget if I had it above the protected section, or in the private section.

uint8_t _keys_pressed[10];

Now that we have a place to store the key presses, we need a function to do that. This is based on the press() function in the regular keyboard library.

void USBKeyboard::press_button(uint8_t c)
{
    if(_keys_pressed[0] != c && _keys_pressed[1] != c &&
    _keys_pressed[2] != c && _keys_pressed[3] != c &&
    _keys_pressed[4] != c && _keys_pressed[5] != c &&
    _keys_pressed[6] != c && _keys_pressed[7] != c &&
    _keys_pressed[8] != c && _keys_pressed[9] != c)
    {
        for(int i = 0; i < 10 ; i++)
        {
            if(_keys_pressed[i] == 0)
            {
                _keys_pressed[i] = c;
                //////////////////////////////////////////////////////////
                // If we don't break, it'll loop through and put the    //
                // character in all 10 slots, since we've already       //
                // checked if it was in the array *BEFORE* starting the //
                // loop.                                                //
                //////////////////////////////////////////////////////////
                break;
            }
        }
    }

}

Now we need a function to send the keys. This is a modified version of the key_code() function already present in the file.

bool USBKeyboard::sendReleaseAll()
{
    _mutex.lock();

    // Testing with hardcoded values of array size 10, and 
    // report size 13.

    // Send simulated keyboard buttons, and empty the button pressed buffer.
    // Returns true if successful.
    HID_REPORT report;

    report.data[0] = REPORT_ID_KEYBOARD;
    report.data[1] = 0;
    report.data[2] = 0;
    for(int i = 3; i < 13; i++)
    {
        report.data[i] = keymap[_keys_pressed[i-3]].usage;
    }

    report.length = 13;

    if (!send(&report)) {
        _mutex.unlock();
        return false;
    }

    for(int i = 3; i < 13; i++)
    {
        report.data[i] = 0;
    }

    emptyButtonBuffer();

    if (!send(&report)) {
        _mutex.unlock();
        return false;
    }


    _mutex.unlock();
    return true;

}

You will need to modify the key_code() function they give by adding a few lines to the array, and changing the report length. This is important because: if your reports don't list the correct length, the function won't work, and nothing will be sent.

report.data[9] = 0;
report.data[10] = 0;
report.data[11] = 0;
report.data[12] = 0;

report.length = 13;

You may have noticed, but I used a function called emptyButtonBuffer() to clear the _keys_pressed array.

void USBKeyboard::emptyButtonBuffer()
{
    // Using hard-coded value of 10 for keys pressed array for testing.
    // Empties the pressed buttons buffer.
    // Buffer is 10 (0 through 9) long.
    for(int i = 0; i < 10; i++)
    {
        _keys_pressed[i] = 0;
    }
}

These are the basic changes. There is more that can be done, but this is what I had, and it was working properly. If you decide to use my file, you'll need to fix the filename which I left as untitled to avoid any unintended overwrites. I suggest either using my functions as templates, or only copying sections you want into your keyboard.cpp file, since a newer keyboard.cpp file may reference newer changes in the mbed_os library (I'll be doing this myself in the next week or two).
Untitled-1.cpp (23.7 KB)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.