Voila, une version amélioré qui gère pas mal de touches, par contre il faut un terminal qui gère l’affichage de l’utf8 sinon par exemple un é ou d’autres symboles ne passe pas. J’ai cherché pas mal pour trouver quel logiciel de terminal série fonctionne et bien putty marche très bien.
Si quelqu’un veut ajouter des touches il est possible d’activer le mode debug en mettant cette ligne a 1:
#define DEBUG_KEYS 1
Et du coup sa affiche le numero de la touche.
Je me suis aidé de chatgpt pour aller plus vite… Voici le code que j’obtiens, j’ai un peu galéré avec certains touches, mais le mode debug facilite les choses…
Aperçu de ce que sa donne dans putty:
Le code actuel:
#include <SPI.h>
#include <usbhub.h>
#include <hidboot.h>
#include <HardwareSerial.h>
// ====== DEBUG (1 = ON pour logger mod/usage, 0 = OFF) ======
#define DEBUG_KEYS 1
// --- MAX3421E (ESP32-S2) ---
#define MAX_SS 5 // CS du MAX3421E
#define MAX_INT 3 // INT du MAX3421E
// --- LED blink ---
const int ledPin = 15;
unsigned long lastBlink = 0;
bool ledState = false;
// --- UART1 (TX=17, RX=18) ---
HardwareSerial Debug(1);
// --- Modificateurs HID ---
#define HID_LCTRL 0x01
#define HID_LSHIFT 0x02
#define HID_LALT 0x04
#define HID_LGUI 0x08
#define HID_RCTRL 0x10
#define HID_RSHIFT 0x20
#define HID_RALT 0x40
#define HID_RGUI 0x80
static inline bool hasShift(uint8_t m){ return m & (HID_LSHIFT|HID_RSHIFT); }
static inline bool hasAltGr(uint8_t m){ return (m & HID_RALT) || ((m & HID_LCTRL) && (m & HID_LALT)); }
USB Usb;
USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKbd(&Usb);
// petit helper pour afficher une ligne debug uniforme
void logUsage(uint8_t mod, uint8_t usage, const char* out) {
#if DEBUG_KEYS
Debug.print("[key] usage=0x");
Debug.print(usage, HEX);
Debug.print(" (");
Debug.print((int)usage);
Debug.print("), mod=0x");
Debug.print(mod, HEX);
Debug.print(" -> '");
Debug.print(out);
Debug.println("'");
#endif
}
// --------- MAP FR PAR USAGE (sans OemToAscii) ---------
// renvoie une chaîne C (char*) à imprimer, ou "" si rien
const char* mapFR(uint8_t usage, uint8_t mod)
{
bool s = hasShift(mod);
bool g = hasAltGr(mod);
// Lettres spéciales (A<->Q, W<->Z)
switch (usage) {
case 0x04: return s ? "Q" : "q"; // US 'A' -> FR 'q'/'Q'
case 0x14: return s ? "A" : "a"; // US 'Q' -> FR 'a'/'A'
case 0x1A: return s ? "Z" : "z"; // US 'W' -> FR 'z'/'Z'
case 0x1D: return s ? "W" : "w"; // US 'Z' -> FR 'w'/'W'
case 0x10: return s ? "?" : ","; // touche , / ?
case 0x33: return s ? "M" : "m";
}
// Lettres communes (B..N, O..P, R..Y) — M a sa touche dédiée plus bas
if (usage >= 0x05 && usage <= 0x1D) {
char base = 'a' + (usage - 0x04);
char outc = s ? (char)toupper(base) : base;
static char buf1[2]; buf1[0]=outc; buf1[1]='\0';
return buf1;
}
// Chiffres 1..0 (usages 0x1E..0x27)
switch (usage) {
case 0x1E: if (g) return ""; return s ? "1" : "&";
case 0x1F: if (g) return "~"; return s ? "2" : "é";
case 0x20: if (g) return "#"; return s ? "3" : "\"";
case 0x21: if (g) return "{"; return s ? "4" : "'";
case 0x22: if (g) return "["; return s ? "5" : "(";
case 0x23: if (g) return "|"; return s ? "6" : "-";
case 0x24: if (g) return "`"; return s ? "7" : "è";
case 0x25: if (g) return "\\\\"; return s ? "8" : "_";
case 0x26: if (g) return "^"; return s ? "9" : "ç";
case 0x27: if (g) return "@"; return s ? "0" : "à";
}
// Après 0 : - et =
switch (usage) {
case 0x2D: return g ? "]" : (s ? "°" : ")"); // FR: ) / ° (+AltGr ])
case 0x2E: return g ? "}" : (s ? "+" : "="); // FR: = / + (+AltGr })
}
// Autour de P : [ ] \ (en FR: ^/¨, $/£, */µ)
switch (usage) {
case 0x2F: return s ? "¨" : "^"; // dead keys, ici non composées
case 0x30: return g ? "¤" : (s ? "£" : "$");
case 0x31: return s ? "µ" : "*";
}
// M, ù/% (en FR : M correspond à l'usage US ';', et ù/% à US quote)
switch (usage) {
case 0x34: return s ? "%" : "ù"; // US quote -> FR 'ù' / '%'
}
// Bas de clavier — (ton mapping actuel)
switch (usage) {
case 0x36: return s ? "." : ";";
case 0x37: return s ? "/" : ":";
case 0x38: return s ? "§" : "!";
}
// Touche ISO près de Shift gauche (peut ne pas servir sur ton modèle)
if (usage == 0x64) return hasShift(mod) ? "!" : "§";
// Espace / Enter / Tab
switch (usage) {
case 0x2C: return " ";
case 0x28: return "\n";
case 0x2B: return "\t";
}
// Pavé numérique (chiffres + virgule)
if (usage >= 0x59 && usage <= 0x63) {
static const char* kp[] = { "1","2","3","4","5","6","7","8","9","0","." };
if (usage == 0x63) return ","; // virgule décimale FR
return kp[usage - 0x59];
}
// Opérateurs pavé num
switch (usage) {
case 0x54: return "/"; // KP /
case 0x55: return "*"; // KP *
case 0x56: return "-"; // KP -
case 0x57: return "+"; // KP +
case 0x58: return "\n"; // KP Enter
}
return ""; // inconnu
}
// --------- Parser ----------
class KbdRptParser : public KeyboardReportParser {
void OnKeyDown(uint8_t mod, uint8_t usage) override {
// on prépare 'out' pour logger la même ligne pour toutes les touches
const char* out = "";
// touches spéciales (demandées)
switch (usage) {
case 0x2A: out = "[bs retour]"; break; // Retour arrière
case 0x4F: out = "[fleche droite]"; break; // Flèche droite
case 0x50: out = "[fleche gauche]"; break; // Flèche gauche
case 0x51: out = "[fleche bas]"; break; // Flèche bas
case 0x52: out = "[fleche haut]"; break; // Flèche haut
default: /* pas spécial -> on mappe après */ break;
}
// si pas une touche spéciale, on mappe via ta table
if (*out == '\0') {
out = mapFR(usage, mod);
}
// log du code touche + caractère mappé (si DEBUG_KEYS=1)
logUsage(mod, usage, out);
// impression effective
if (out && *out) Debug.print(out);
}
} KbdPrs;
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Debug.begin(115200, SERIAL_8N1, 18, 17); // RX=18, TX=17
Debug.println("\n[UART1] Boot");
SPI.begin();
pinMode(MAX_SS, OUTPUT);
digitalWrite(MAX_SS, HIGH);
pinMode(MAX_INT, INPUT_PULLUP);
Debug.println("Init USB Host (MAX3421E)...");
int r = Usb.Init();
if (r != 0) {
Debug.print("❌ Init échouée (code "); Debug.print(r); Debug.println(").");
while (true) { digitalWrite(ledPin, HIGH); delay(120); digitalWrite(ledPin, LOW); delay(120); }
}
HidKbd.SetReportParser(0, (HIDReportParser*)&KbdPrs);
Debug.println("✅ USB Host prêt — branche un clavier.");
}
void loop() {
Usb.Task();
// Blink non bloquant (1 Hz)
unsigned long now = millis();
if (now - lastBlink >= 500) {
lastBlink = now;
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
}
}
Maintenant un petit programme qui utilise le mode HID de l’esp32-s2 pour envoyer du texte comme le fait un clavier (testé):
#include <Arduino.h>
#include <USB.h>
#include <USBHIDKeyboard.h>
USBHIDKeyboard Keyboard;
void setup() {
// Démarre la pile USB et le périphérique HID clavier
USB.begin();
Keyboard.begin();
// Laisse le temps à l’OS d’initialiser le périphérique USB
delay(1500);
}
void loop() {
// Envoie "test" + retour à la ligne comme si c’était tapé au clavier
Keyboard.println("test");
// Attends 5 secondes
delay(5000);
}