Arduino Micro + clickermann - 2

Статья 2. Обход любых защит. DLL для общения с контроллером!

Автор:dramster

Первая часть /post/arduino-micro-+-clickerman

Не прошло и года, как у меня все-же получилось написать длл для общения с ком портом, а именно с ардуиномикро. По сравнению с командной строкой, работает шустро и незаметно.
При написании никаких дополнительных компонентов для работы с ком не использовал. С ними оказалось намного все сложнее.
Вобщем, пару вечеров, куча статей и форумов, вот первый, и вполне рабочий вариант.
Кто в теме, или вдруг загорится этой темой, код длл делфи10:

Код: Delphi

library micro_com;

uses    Windows, SysUtils;

//------------------------------------------------------------------------------
// Основное тело функции, идет на экспорт, вызывается из кликера
function execute( _mas: pInteger; _size: Integer): Integer; export; stdcall;

type
    pIntArr = array[0..0] of Integer;
var
    DCB   : TDCB;
    hPort : THandle;
    port_num : integer;
    param : integer;
    byete_res: Cardinal;
    str : string;
    len : integer;
begin
    port_num := pIntArr(_mas^)[0];
    param := pIntArr(_mas^)[_size-1];

    // 1. Открываем файл
    hPort :=
                    CreateFile(PChar('COM'+IntToStr(port_num)),
                    GENERIC_READ + GENERIC_WRITE, 0, nil,
                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    // 2. Контроль ошибок
    if hPort = INVALID_HANDLE_VALUE then begin
        // Обнаружена ошибка, порт открыть не удалось
        result := 1;
        exit;
    end;

    // 3. Чтение текущих настроек порта
    if GetCommState(hPort, DCB) then ;
    // 4. Настройки:
    // Скорость обмена
    DCB.BaudRate := 9600;
    // Число бит на символ
    DCB.ByteSize := 8;
    // Стоп-биты
    DCB.StopBits := 1;
    // Четность
    DCB.Parity   := 0;
    // Какая-то херь непонятная
    DCB.Flags := 20625;
    // 5. Передача настроек
    if not SetCommState(hPort, DCB) then begin{ошибка настройки порта}
        result := 2;
        exit;
    end;
    // 6. Настройка буферов порта (очередей ввода и вывода)
    if not SetupComm(hPort, 16, 16) then begin{ошибка настройки буферов}
        result := 3;
        exit;
    end;
    // 7. Сброс буферов и очередей
    if PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR orPURGE_RXCLEAR) then
        // 8. Запись в порт
        str := intToStr(param);
        len := Length(str);
        WriteFile(hPort, PChar(str)^, len*2, byete_res, nil);
        // 9. Закрытие порта
        CloseHandle(hPort);
        result := 5;
    end;

//------------------------------------------------------------------------------

// список экспорта
exports execute;

begin

end.

Скомпилированная библиотека уверенно отправляет в нужный порт любой текст. Примерно так:

Код: Clickermann

CALL ("micro_com.dll", $com, $val)

Нам же, для управления микрой, нужны только числа. Скетч для контроллера взял старый отсюда /post/arduino-micro-+-clickerman. Немного доработал его:

Код: sketch Arduino

#include <mouse.h>
#include <keyboard.h>

unsigned long par = 0;
String instring = "";
int kmfunct = 0;
int x_cor = 0;
int y_cor = 0;
int mult = 0;
int inchar = 0;

void setup() {
    Serial.begin(9600);
    Mouse.begin();
    Keyboard.begin();
    }

void loop() {

    while(Serial.available() > 0){
    inchar = Serial.read();
    if (isDigit(inchar)) {
        instring += (char)inchar;
        }
    }
    par = instring.toInt();
    instring = "";

    if (par > 0) {
        kmfunct =  par/16777216 ;
        switch (kmfunct) {

            case 1:  //Mouse.click
                Mouse.click(par - kmfunct*16777216);
                break;
            case 2:  //  Mouse.move
                x_cor = (par - kmfunct*16777216)/256;
                y_cor = par - x_cor*256 - kmfunct*16777216;
                if (x_cor > 127) x_cor = 127 - x_cor;
                if (y_cor > 127) y_cor = 127 - y_cor;
                Mouse.move(x_cor, y_cor, 0);
                break;
            case 3: //Mouse.press
                Mouse.press(par - kmfunct*16777216);
                break;
            case 4: //Mouse.release
                Mouse.release(par - kmfunct*16777216);
                break;
            case 5:  //Mouse.dblclick
                Mouse.click(par - kmfunct*16777216);
                delay(50);
                Mouse.click(par - kmfunct*16777216);
                break;
            case 6: //wheel.down.up
                mult = par - kmfunct*16777216;
                if (mult > 127) mult = 127 - mult;
                Mouse.move(0, 0, mult);
            case 7: // Keyboard.keydown
                Keyboard.press(par - kmfunct*16777216);
                break;
            case 8: // Keyboard.keyup
                Keyboard.release(par - kmfunct*16777216);
                break;
            case 9: // Keyboard.keypress
                Keyboard.write(par - kmfunct*16777216);
                break;
        }
    }
    par = 0;
}
</keyboard.h></mouse.h>

Библиотека с подпрограммами для кликермана тут:
Arduino_mouse_keyboard_4.13.cms (4.68 КБ)
Arduino_mouse_keyboard_4.14.cms (3.36 КБ)

Код: Clickermann

$com = 5   //свой порт

//#name "Arduino_mouse&keyboard"

////////////////////////////////////////////////

// Все процедуры с мышью и клавиатурой через ардуино

//micro_move ($x_cor, $y_cor)
//micro_lclick ($x_cor, $y_cor)
//micro_rclick ($x_cor, $y_cor)
//micro_mclick ($x_cor, $y_cor)
//micro_ldown ($x_cor, $y_cor)
//micro_rdown ($x_cor, $y_cor)
//micro_mdown ($x_cor, $y_cor)
//micro_lup ($x_cor, $y_cor)
//micro_rup ($x_cor, $y_cor)
//micro_mup ($x_cor, $y_cor)
//micro_dblclick ($x_cor, $y_cor)
//micro_wheeldown ($mult)
//micro_wheelup ($mult)

// вместо $char_ASCII писать не код клавиши, а символ ASCII.
// в ардуино как-то тупо сделали клавиатурные нажатия :/
//micro_keydown ($char_ASCII)
//micro_keyup ($char_ASCII)
//micro_keypress ($char_ASCII)


//move
SUB(micro_move, $x_cor, $y_cor)
    WHILE(DIST($x_cor, $y_cor, $_xmouse, $_ymouse) > 3)
        $x_temp = $_xmouse
        $y_temp = $_ymouse

        $x_dist = $x_cor - $_xmouse
        $y_dist = $y_cor - $_ymouse

        IF($x_dist < 0)
            $x_dist = 127 + int(SQRT(ABS($x_dist*4)))
        else
            $x_dist =  int(SQRT(ABS($x_dist*4)))
        END_IF
        IF($y_dist < 0)
            $y_dist = 127 + int(SQRT(ABS($y_dist*4)))
        else
            $y_dist =  int(SQRT(ABS($y_dist*4)))
        END_IF
        CALL ("micro_com.dll", $com, 33554432 + $x_dist*256 + $y_dist)

    END_CYC
END_SUB

//lclick
SUB(micro_lclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777217)
END_SUB

//rclick
SUB(micro_rclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777218)
END_SUB

//mclick
SUB(micro_mclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777219)
END_SUB

//ldown
SUB(micro_ldown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331649)
END_SUB

//rdown
SUB(micro_rdown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331650)
END_SUB

//mdown
SUB(micro_mdown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331651)
END_SUB

//lup
SUB(micro_lup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108865)
END_SUB

//rup
SUB(micro_rup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108866)
END_SUB

//mup
SUB(micro_mup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108867)
END_SUB

//dblclick
SUB(micro_dblclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 83886081)
END_SUB

//wheeldown
SUB(micro_wheeldown, $mult)
    CALL ("micro_com.dll", $com, 100663423 + $mult)
END_SUB

//wheelup
SUB(micro_wheelup, $mult)
    CALL ("micro_com.dll", $com, 100663296 + $mult)
END_SUB

//keydown
SUB(micro_keydown, $char_ASCII)
    CALL ("micro_com.dll", $com, 117440512 + code($char_ASCII))
END_SUB

//keyup
SUB(micro_keyup, $char_ASCII)
    CALL ("micro_com.dll", $com, 134217728 + code($char_ASCII))
END_SUB

//keypress
SUB(micro_keypress, $char_ASCII)
    CALL ("micro_com.dll", $com, 150994944 + code($char_ASCII))
END_SUB

Даже и не уверен, придумают ли защиту от такого аппаратного управления машиной  ;).

Подключайтесь, проверяйте. Я проверил и использовал лишь в одной защищенной древнючей игре MTA_SA. Не смотря на ее древнючесть, они уже давно впилили защиту от кликеров. Сам контроллер не сильно и дорогой, глянул - от 350р. Я вроде еще за 280 когда-то купил.

Скачать dll для х32 систем: micro_com.dll (133 КБ)


А теперь поподробнее, с чего начинать, что купить, как прошить, как запустить...

1. Нам нужен сам контроллер ардуино. Подойдут только те, которые определяются на ПК как мышь и клавиатура. Те, о которых я в курсе - Arduino Micro, Arduino Pro Micro, Arduino Leonardo.

http://arduino.ru/sites/default/files/resize/u3731/arduinomicrofront-380x171.jpg


2. Подключаем наш девайс к ПК в любой USB. Смотрим в диспетчер устройств. Должно появиться три новых устройства - клавиатура HID, HID совместимая мышь, устройство с последовательным интерфейсом USB (COM). Номер COM порта запоминаем.

https://i.imgur.com/gd5z0pa.png


3. Далее нужно прошить наш контроллер. Для этого нужен софт. Качаем с оффсайта ардуино последнюю версию Arduino IDE https://www.arduino.cc/en/software . Я использую портативную версию для windows - "Windows ZIP file". Она не требует установки, просто распаковать из архива, и готово, можно пользоваться.

https://i.imgur.com/hu6uEm8.png


4. Настраиваем IDE под наш контроллер. Меню - инструменты - плата: - Arduino Micro, либо Leonardo в зависимости от того что там у вас. Меню - инструменты - порт: - выбираем порт к которому подключен контроллер.

https://i.imgur.com/lVEB3xt.png https://i.imgur.com/cFuMNws.png


5. Все, можно загружать скетч. Берем тот что я написал, либо пишите свой. Мой:

Код скетча:

#include <mouse.h>
#include <keyboard.h>

unsigned long par = 0;
String instring = "";
int kmfunct = 0;
int x_cor = 0;
int y_cor = 0;
int mult = 0;
int inchar = 0;

void setup() {
    Serial.begin(9600);
    Mouse.begin();
    Keyboard.begin();
}

void loop() {

    while(Serial.available() > 0){
    inchar = Serial.read();
    if (isDigit(inchar)) {
        instring += (char)inchar;
        }
    }
    par = instring.toInt();
    instring = "";

    if (par > 0) {
        kmfunct =  par/16777216 ;
        switch (kmfunct) {
            case 1:  //Mouse.click
                Mouse.click(par - kmfunct*16777216);
                break;
            case 2:  //  Mouse.move
                x_cor = (par - kmfunct*16777216)/256;
                y_cor = par - x_cor*256 - kmfunct*16777216;
                if (x_cor > 127) x_cor = 127 - x_cor;
                if (y_cor > 127) y_cor = 127 - y_cor;
                Mouse.move(x_cor, y_cor, 0);
                break;
            case 3: //Mouse.press
                Mouse.press(par - kmfunct*16777216);
                break;
            case 4: //Mouse.release
                Mouse.release(par - kmfunct*16777216);
                break;
            case 5:  //Mouse.dblclick
                Mouse.click(par - kmfunct*16777216);
                delay(50);
                Mouse.click(par - kmfunct*16777216);
                break;
            case 6: //wheel.down.up
                mult = par - kmfunct*16777216;
                if (mult > 127) mult = 127 - mult;
                Mouse.move(0, 0, mult);
            case 7: // Keyboard.keydown
                Keyboard.press(par - kmfunct*16777216);
                break;
            case 8: // Keyboard.keyup
                Keyboard.release(par - kmfunct*16777216);
                break;
            case 9: // Keyboard.keypress
                Keyboard.write(par - kmfunct*16777216);
                break;
        }
    }
    par = 0;
}
</keyboard.h></mouse.h>

Копируете и вставляете в редактор arduino. Жмете кнопку "проверить", пойдет компиляция скетча. После завершения в логе будет что-то типа:

Скетч использует 7426 байт (25%) памяти устройства. Всего доступно 28672 байт.
Глобальные переменные используют 265 байт (10%) динамической памяти, оставляя 2295 байт для локальных переменных. Максимум: 2560 байт.

Значит все отлично, жмем кнопку "загрузка" и ждем пока скетч загрузится в контроллер. Если все в норме, то по итогу в логе будет: загрузка завершена, и тоже самое что и после проверки.

https://i.imgur.com/UduTXYU.png


6. Контроллер готов и ждет команды из COM порта. Для отправки сообщения в наш порт я написал DLL библиотеку  "micro_com.dll". Берем во вложении первого поста, либо вот с ядиска https://disk.yandex.ru/d/YuMXDEFLhWiD6A . Качаем (либо копируем) библиотеку с процедурами мыши и клавиатуры для Clickermann "Arduino_mouse_keyboard.cms" , во вложении, либо код из поста выше, либо с ядиска https://disk.yandex.ru/d/kmqlsabjb4RJvg . Кидаем эти два файла в одну папку. Открываем "Arduino_mouse_keyboard.cms" и прописываем в переменную $com номер порта, к которому подключена ардуина.


7. Создаем наш основной скрипт, либо редактируем уже существующий. Подключаем в него "Arduino_mouse_keyboard.cms".

Код: Clickermann

#include "Arduino_mouse_keyboard.cms"

Все процедуры, которые я пока написал:

Код: Clickermann

//micro_move($x_cor, $y_cor)
//micro_lclick($x_cor, $y_cor)
//micro_rclick($x_cor, $y_cor)
//micro_mclick($x_cor, $y_cor)
//micro_ldown($x_cor, $y_cor)
//micro_rdown($x_cor, $y_cor)
//micro_mdown($x_cor, $y_cor)
//micro_lup($x_cor, $y_cor)
//micro_rup($x_cor, $y_cor)
//micro_mup($x_cor, $y_cor)
//micro_dblclick($x_cor, $y_cor)
//micro_wheeldown($mult)
//micro_wheelup($mult)

// вместо $char_ASCII писать не код клавиши, а символ ASCII.
// в ардуино как-то тупо сделали клавиатурные нажатия :/
// пока поддерживают только печатные символы, в будущем добавлю подпрограмму для клавиш-модификаторов.
//micro_keydown($char_ASCII)
//micro_keyup($char_ASCII)
//micro_keypress($char_ASCII)

Ну и для проверки можно подергать курсором. Пишем к примеру такой код:

Код: Clickermann

#include "Arduino_mouse_keyboard.cms"

WAIT(2)
micro_move(100, 100)
WAIT(2)
micro_move(500, 500)
WAIT(2)
micro_move(500, 100)
WAIT(2)
micro_move(100, 100)
HALT

Жмем "применить" и сохраняем скрипт в папку с "micro_com.dll" и "Arduino_mouse_keyboard.cms". Запускаем и смотрим как курсор двигается по прописанным координатам.



 8. Радуемся.


Если курсор не двигается, то ищем где мы накосячили. DLL может помочь в этом. Функция из библиотеки возвращает код, сообщая, на каком моменте остановилась работа по общению с COM портом. Если все в норме, функция должна возвратить "5"

Код: Clickermann

#include "Arduino_mouse_keyboard.cms"

WAIT(2)
micro_move(100, 100)
PRINT($_return1)  //должно быть "5", иначе - пишите в этой теме, и подумаем в чем ошибка.
HALT

Подробно о библиотеках Mouse и Keyboard для ардуино тут - https://doc.arduino.ua/ru/prog/MouseKeyboard либо на оффсайте на английском.
Коды клавиш-модификаторов тут - https://doc.arduino.ua/ru/prog/KeyboardModifiers. Для них нужно будет писать отдельную подпрограмму, либо вызывать индивидуально.

DLL написана для х32 систем, соответственно версия кликермана должна быть х32!!!


Вот библиотека для всех версий (кроме х64), включая 4.13 и старше. Написал основные клавиши и клавиши модификаторы. Не достающие клавиши можете дописать сами.

Код: Clickermann

$com = 5  //свой порт

//"Arduino_mouse&keyboard"  для версии 4.13 и старше.

////////////////////////////////////////////////

// Все процедуры с мышью и клавиатурой через ардуино

//micro_move ($x_cor, $y_cor)
//micro_lclick ($x_cor, $y_cor)
//micro_rclick ($x_cor, $y_cor)
//micro_mclick ($x_cor, $y_cor)
//micro_ldown ($x_cor, $y_cor)
//micro_rdown ($x_cor, $y_cor)
//micro_mdown ($x_cor, $y_cor)
//micro_lup ($x_cor, $y_cor)
//micro_rup ($x_cor, $y_cor)
//micro_mup ($x_cor, $y_cor)
//micro_dblclick ($x_cor, $y_cor)
//micro_wheeldown ($mult)
//micro_wheelup ($mult)


//micro_keydown (key_)
//micro_keyup (key_)
//micro_keypress (key_)

//коды клавиш, если чегото не хватает, дописывайте сами.
#define key_0:49
#define key_1:50
#define key_2:51
#define key_3:52
#define key_4:53
#define key_5:54
#define key_6:55
#define key_7:56
#define key_8:57
#define key_9:58
#define key_a:97
#define key_b:98
#define key_c:99
#define key_d:100
#define key_e:101
#define key_f:102
#define key_g:103
#define key_h:104
#define key_i:105
#define key_j:106
#define key_k:107
#define key_l:108
#define key_m:109
#define key_n:110
#define key_o:111
#define key_p:112
#define key_q:113
#define key_r:114
#define key_s:115
#define key_t:116
#define key_u:117
#define key_v:118
#define key_w:119
#define key_x:120
#define key_y:121
#define key_z:122
#define KEY_LEFT_CTRL:128
#define KEY_LEFT_SHIFT:129
#define KEY_LEFT_ALT:130
#define KEY_LEFT_GUI:131
#define KEY_RIGHT_CTRL:132
#define KEY_RIGHT_SHIFT:133
#define KEY_RIGHT_ALT:134
#define KEY_RIGHT_GUI:135
#define KEY_UP_ARROW:218
#define KEY_DOWN_ARROW:217
#define KEY_LEFT_ARROW:216
#define KEY_RIGHT_ARROW:215
#define KEY_BACKSPACE:178
#define KEY_TAB:179
#define KEY_RETURN:176
#define KEY_ESC:177
#define KEY_INSERT:209
#define KEY_DELETE:212
#define KEY_PAGE_UP:211
#define KEY_PAGE_DOWN:214
#define KEY_HOME:210
#define KEY_END:213
#define KEY_CAPS_LOCK:193
#define KEY_F1:194
#define KEY_F2:195
#define KEY_F3:196
#define KEY_F4:197
#define KEY_F5:198
#define KEY_F6:199
#define KEY_F7:200
#define KEY_F8:201
#define KEY_F9:202
#define KEY_F10:203
#define KEY_F11:204
#define KEY_F12:205


//move
SUB(micro_move, $x_cor, $y_cor)
    WHILE(DIST($x_cor, $y_cor, $_xmouse, $_ymouse) > 3)
        $x_temp = $_xmouse
        $y_temp = $_ymouse

        $x_dist = $x_cor - $_xmouse
        $y_dist = $y_cor - $_ymouse

        IF($x_dist < 0)
            $x_dist = 127 + int(SQRT(ABS($x_dist*4)))
        else
            $x_dist =  int(SQRT(ABS($x_dist*4)))
        END_IF
        IF($y_dist < 0)
            $y_dist = 127 + int(SQRT(ABS($y_dist*4)))
        else
            $y_dist =  int(SQRT(ABS($y_dist*4)))
        END_IF
        CALL ("micro_com.dll", $com, 33554432 + $x_dist*256 + $y_dist)
    END_CYC
END_SUB

//lclick
SUB(micro_lclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777217)
END_SUB

//rclick
SUB(micro_rclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777218)
END_SUB

//mclick
SUB(micro_mclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 16777219)
END_SUB

//ldown
SUB(micro_ldown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331649)
END_SUB

//rdown
SUB(micro_rdown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331650)
END_SUB

//mdown
SUB(micro_mdown, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 50331651)
END_SUB

//lup
SUB(micro_lup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108865)
END_SUB

//rup
SUB(micro_rup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108866)
END_SUB

//mup
SUB(micro_mup, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 67108867)
END_SUB

//dblclick
SUB(micro_dblclick, $x_cor, $y_cor)
    micro_move($x_cor, $y_cor)
    CALL ("micro_com.dll", $com, 83886081)
END_SUB

//wheeldown
SUB(micro_wheeldown, $mult)
    CALL ("micro_com.dll", $com, 100663423 + $mult)
END_SUB

//wheelup
SUB(micro_wheelup, $mult)
    CALL ("micro_com.dll", $com, 100663296 + $mult)
END_SUB

//keydown
SUB(micro_keydown, $key_)
    CALL ("micro_com.dll", $com, 117440512 + int($key_))
END_SUB

//keyup
SUB(micro_keyup, $key_)
    CALL ("micro_com.dll", $com, 134217728 + int($key_))
END_SUB

//keypress
SUB(micro_keypress, $key_)
    CALL ("micro_com.dll", $com, 150994944 + int($key_))
END_SUB

Пример по использованию:

Код: Clickermann

#include "Arduino_mouse_keyboard.cms"

//контроллер выделяет текст активного окна и удаляет его
WAIT(1)
micro_keydown(KEY_RIGHT_CTRL) //зажимает левый контрал
micro_keydown(key_a)    //зажимает клавишу"A"
WAITMS(100)
micro_keyup(key_a)    //отпускает клавишу"A"
micro_keyup(KEY_RIGHT_CTRL) //отпускает левый контрал
WAITMS(100)
micro_keypr...

Добавленные клавиши:

Код: Text

key_0
key_1
key_2
key_3
key_4
key_5
key_6
key_7
key_8
key_9
key_a
key_b
key_c
key_d
key_e
key_f
key_g
key_h
key_i
key_j
key_k
key_l
key_m
key_n
key_o
key_p
key_q
key_r
key_s
key_t
key_u
key_v
key_w
key_x
key_y
key_z
KEY_LEFT_CTRL
KEY_LEFT_SHIFT
KEY_LEFT_ALT
KEY_LEFT_GUI
KEY_RIGHT_CTRL
KEY_RIGHT_SHIFT
KEY_RIGHT_ALT
KEY_RIGHT_GUI
KEY_UP_ARROW
KEY_DOWN_ARROW
KEY_LEFT_ARROW
KEY_RIGHT_ARROW
KEY_BACKSPACE
KEY_TAB
KEY_RETURN
KEY_ESC
KEY_INSERT
KEY_DELETE
KEY_PAGE_UP
KEY_PAGE_DOWN
KEY_HOME
KEY_END
KEY_CAPS_LOCK
KEY_F1
KEY_F2
KEY_F3
KEY_F4
KEY_F5
KEY_F6
KEY_F7
KEY_F8
KEY_F9
KEY_F10
KEY_F11
KEY_F12

Вот такой прикольный корпус есть для ардуинки

Кейс для Arduino Mini_1 Кейс для Arduino Mini_2

Спасибо большое за весь предоставленный материал, автору - dramster