Problema di stampa caratteri con arduino micro e libreria keyboard.h

Salve a tutti, scrivo per un problema nell'utilizzare arduino micro come una tastiera usb, quando provo a stampare dei caratteri, il risultato è differente:

Keyboard.print("/ciao"); output: -ciao

Allora ho provato a stampare tutti i caratteri disponibili fino al 127 con il ciclo for, ma ho notato che il carattere ">" non si può ricreare.
Mi servirebbe per indirizzare l'output di un comando del prompt, su un file di testo.
Qualcuno può aiutarmi, grazie.

Se qualcuno fosse interessato alla soluzione andate direttamente negli ultimi 2/3 commenti della seconda pagina

E' un problema di mappatura dei tasti/caratteri, la Keyboard mappa una tabella ASCII corrispondente a quella US Standard mentre tu vorresti usare quella italiana (infatti dove noi sulla tastiera abbiamo "-" in quella US c'è "/").

Puoi modificare questa mappatura aprendo il file HID.cpp (si trova sotto alla cartella cores\arduino\ che trovi sotto a quella di Arduino, ma fatti prima una copia di sicurezza) e modificando l'array che contiene la mappa dei caratteri ASCII ovvero:

const uint8_t _asciimap[128] =

Non ho trovato una asciimap italiana già pronta, quindi temo che dovrai confrontare la tastiera US Standard con quella Italiana e da questo confronto modificare opportunamente il file HID.cpp.

PEr altre info sulla tastiera via USB vedi QUESTO documento.

Grazie mille risposta eccezionale. Ora non dovrei avere problemi per ho già un file di testo con tutte le conversioni

Non capisco, perchè il file .cpp l'ho trovato così:

/*
   Copyright (c) 2015, Arduino LLC
   Original code (pre-library): Copyright (c) 2011, Peter Barrett

   Permission to use, copy, modify, and/or distribute this software for
   any purpose with or without fee is hereby granted, provided that the
   above copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
   BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   SOFTWARE.
 */

#include "HID.h"

#if defined(USBCON)

HID_& HID()
{
 static HID_ obj;
 return obj;
}

int HID_::getInterface(uint8_t* interfaceCount)
{
 *interfaceCount += 1; // uses 1
 HIDDescriptor hidInterface = {
 D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE),
 D_HIDREPORT(descriptorSize),
 D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
 };
 return USB_SendControl(0, &hidInterface, sizeof(hidInterface));
}

int HID_::getDescriptor(USBSetup& setup)
{
 // Check if this is a HID Class Descriptor request
 if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
 if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; }

 // In a HID Class Descriptor wIndex cointains the interface number
 if (setup.wIndex != pluggedInterface) { return 0; }

 int total = 0;
 HIDSubDescriptor* node;
 for (node = rootNode; node; node = node->next) {
 int res = USB_SendControl(TRANSFER_PGM, node->data, node->length);
 if (res == -1)
 return -1;
 total += res;
 }
 
 // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol
 // due to the USB specs, but Windows and Linux just assumes its in report mode.
 protocol = HID_REPORT_PROTOCOL;
 
 return total;
}

uint8_t HID_::getShortName(char *name)
{
 name[0] = 'H';
 name[1] = 'I';
 name[2] = 'D';
 name[3] = 'A' + (descriptorSize & 0x0F);
 name[4] = 'A' + ((descriptorSize >> 4) & 0x0F);
 return 5;
}

void HID_::AppendDescriptor(HIDSubDescriptor *node)
{
 if (!rootNode) {
 rootNode = node;
 } else {
 HIDSubDescriptor *current = rootNode;
 while (current->next) {
 current = current->next;
 }
 current->next = node;
 }
 descriptorSize += node->length;
}

int HID_::SendReport(uint8_t id, const void* data, int len)
{
 auto ret = USB_Send(pluggedEndpoint, &id, 1);
 if (ret < 0) return ret;
 auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len);
 if (ret2 < 0) return ret2;
 return ret + ret2;
}

bool HID_::setup(USBSetup& setup)
{
 if (pluggedInterface != setup.wIndex) {
 return false;
 }

 uint8_t request = setup.bRequest;
 uint8_t requestType = setup.bmRequestType;

 if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
 {
 if (request == HID_GET_REPORT) {
 // TODO: HID_GetReport();
 return true;
 }
 if (request == HID_GET_PROTOCOL) {
 // TODO: Send8(protocol);
 return true;
 }
 if (request == HID_GET_IDLE) {
 // TODO: Send8(idle);
 }
 }

 if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
 {
 if (request == HID_SET_PROTOCOL) {
 // The USB Host tells us if we are in boot or report mode.
 // This only works with a real boot compatible device.
 protocol = setup.wValueL;
 return true;
 }
 if (request == HID_SET_IDLE) {
 idle = setup.wValueL;
 return true;
 }
 if (request == HID_SET_REPORT)
 {
 //uint8_t reportID = setup.wValueL;
 //uint16_t length = setup.wLength;
 //uint8_t data[length];
 // Make sure to not read more data than USB_EP_SIZE.
 // You can read multiple times through a loop.
 // The first byte (may!) contain the reportID on a multreport.
 //USB_RecvControl(data, length);
 }
 }

 return false;
}

HID_::HID_(void) : PluggableUSBModule(1, 1, epType),
                   rootNode(NULL), descriptorSize(0),
                   protocol(HID_REPORT_PROTOCOL), idle(1)
{
 epType[0] = EP_TYPE_INTERRUPT_IN;
 PluggableUSB().plug(this);
}

int HID_::begin(void)
{
 return 0;
}

#endif /* if defined(USBCON) */

Poi l'ho chiuso perchè non c'era quello che dicevi te, successivamente l'ho ricercato e l'ho trovato nel modo giusto.
Ma ora non lo trovo più, e lo ritrovo sempre come quello citato nel "quote",

>Massimiliano_Dolcini: ti ricordo che il codice va nei tag CODE e NON nei tag quote ...
... per questa volta ho corretto io, ma per il futuro tiello presente. Grazie,

Guglielmo

perché la cosa non mi convince?

quella tabella la ho trovata in keyboard.cpp

ma credevo che la tabella ascii non fosse legata alla lingua, la disposizione dei tasti non passa attraverso uno scancode?

Massimiliano_Dolcini:
Non capisco, perchè il file .cpp l'ho trovato così:

Si, a seconda delle versioni installate potrebbe essere differente, in questo caso in quella che hai postato trovi la asciimap nel file "Keyboard.cpp" che trovi in libraries\Keyboard\src\

Ducembarr:
ma credevo che la tabella ascii non fosse legata alla lingua, la disposizione dei tasti non passa attraverso uno scancode?

Si, ma infatti i valori di quell'array sono gli scancode. Analizzando un poco la cosa, di fatto l'indice della tabella è il valore ASCII del carattere che vorresti mandare, e lui manda all'host il relativo scancode.

Per cui ad esempio per il carattere '1', che ha codice ASCII 49, il valore di asciitable[49] è lo scancode 0x1e che corrisponde al tasto 1. Il carattere sopra a quel tasto (ossia con lo shift) è lo scancode in "or" con 0x80 (che rappresenta lo shift) quindi 0x9e. 

Per questo quando fai Keyboard.print("/") il carattere '/',  che ha codice ASCII 47, in quella tabella lo converte in asciitable[47]=0x38 ed il computer, ricevendo 0x38 ed avendo impostato la tastiera italiana, lo interpreta con il tasto che corrisponde allo scancode 0x38 su quella tastiera, ed ecco che quindi esce "-".

In sostanza, per risolvere questo problema ci sono due modi distinti: o su Windows la tastiera virtuale di Arduino la si imposta con layout US, oppure si modifica a manella il file Keyboard.cpp.

EDIT: per il secondo caso, prova questa tabella che ho trovato in rete, da verificare comunque:

const uint8_t _asciimap[128] =
{
	0x00,             // NUL
	0x00,             // SOH
	0x00,             // STX
	0x00,             // ETX
	0x00,             // EOT
	0x00,             // ENQ
	0x00,             // ACK  
	0x00,             // BEL
	0x2a,			// BS	Backspace
	0x2b,			// TAB	Tab
	0x28,			// LF	Enter
	0x00,             // VT 
	0x00,             // FF 
	0x00,             // CR 
	0x00,             // SO 
	0x00,             // SI 
	0x00,             // DEL
	0x00,             // DC1
	0x00,             // DC2
	0x00,             // DC3
	0x00,             // DC4
	0x00,             // NAK
	0x00,             // SYN
	0x00,             // ETB
	0x00,             // CAN
	0x00,             // EM 
	0x00,             // SUB
	0x00,             // ESC
	0x00,             // FS 
	0x00,             // GS 
	0x00,             // RS 
	0x00,             // US 

	0x2c,		   //  ' '
	0x1e|SHIFT,	   // !
	0x1f|SHIFT,	   // "
	0x34|SHIFT,    // # //Rivedere solo modificatori
	0x21|SHIFT,    // $
	0x22|SHIFT,    // %
	0x23|SHIFT,    // &
    0x2d,          // '
	0x25|SHIFT,    // (
	0x26|SHIFT,    // )
	0x30|SHIFT,    // *
	0x30,          // +
	0x36,          // ,
	0x38,          // -
	0x37,          // .
	0x24 | SHIFT,  // /
	0x27,          // 0
	0x1e,          // 1
	0x1f,          // 2
	0x20,          // 3
	0x21,          // 4
	0x22,          // 5
	0x23,          // 6
	0x24,          // 7
	0x25,          // 8
	0x26,          // 9
	0x37|SHIFT,    // :
    0x36|SHIFT,    // ;
	0x00,          // <
	0x27|SHIFT,    // =
	0x00,    // >
	0x2d|SHIFT,    // ?
	//0x33,    // @ //Rivedere solo modificatori
    0x00, //@
	0x04|SHIFT,    // A
	0x05|SHIFT,    // B
	0x06|SHIFT,    // C
	0x07|SHIFT,    // D
	0x08|SHIFT,    // E
	0x09|SHIFT,    // F
	0x0a|SHIFT,    // G
	0x0b|SHIFT,    // H
	0x0c|SHIFT,    // I
	0x0d|SHIFT,    // J
	0x0e|SHIFT,    // K
	0x0f|SHIFT,    // L
	0x10|SHIFT,    // M
	0x11|SHIFT,    // N
	0x12|SHIFT,    // O
	0x13|SHIFT,    // P
	0x14|SHIFT,    // Q
	0x15|SHIFT,    // R
	0x16|SHIFT,    // S
	0x17|SHIFT,    // T
	0x18|SHIFT,    // U
	0x19|SHIFT,    // V
	0x1a|SHIFT,    // W
	0x1b|SHIFT,    // X
	0x1c|SHIFT,    // Y
	0x1d|SHIFT,    // Z
	//0x2f,          // [ //Rivedere solo modificatori
    0x00, // [
    0x35,          // bslash
	//0x30,          // ] //Rivedere solo modificatori
    0x00, // ]
	0x2e|SHIFT,    // ^
	0x38|SHIFT,    // _
	0x00,          // ` //Non c'è
	0x04,          // a
	0x05,          // b
	0x06,          // c
	0x07,          // d
	0x08,          // e
	0x09,          // f
	0x0a,          // g
	0x0b,          // h
	0x0c,          // i
	0x0d,          // j
	0x0e,          // k
	0x0f,          // l
	0x10,          // m
	0x11,          // n
	0x12,          // o
	0x13,          // p
	0x14,          // q
	0x15,          // r
	0x16,          // s
	0x17,          // t
	0x18,          // u
	0x19,          // v
	0x1a,          // w
	0x1b,          // x
	0x1c,          // y
	0x1d,          // z
	//0x2f,    // { //Rivedere solo modificatori
    0x00, //{
	0x35|SHIFT,    // |
	//0x30,    // } //Rivedere solo modificatori
    0x00, //}
	0x00,          // ~ //Non c'è
	0				// DEL
};

Scusate ma non sono ancora riuscito a risolvere, c'è qualcosa che non va, pur provando ad usare il codice che mi ha dato @docdoc, non sono riuscito a risolvere, inoltre se per esempio uso:

Keyboard.write(0x38);

che dovrebbe corrispondere a "/" , salta fuori "8" che sarebbe 0x25.
E se scrivo

Keyboard.print("?");

L'ascii del punto di domanda è 63, a 63 nel file Keyboard.cpp corrisponde ">" (0x37|SHIFT), ma alla fine viene mostrato "_" (0x2d|SHIFT).
Quindi direi che c'è qualcosa che non va

La Keyborad.write chiama la Keyboard.press e poi la Keyboard.release

La Keyboard.press richiama la Keyboard.getKeyCode la quale fa poi la traslazione chiamando la tabella ascii_to_hid per tutti i valori minori di 0x80

In altre parole la write non scrive l'effettivo valore ma usa sempre la tabella.

Ora la tabella è numerata, se non sbaglio Keyboard.write(0x38); stampa il 56esimo valore della tabella, che parte da zero e che è appunto "8"
"/" dovrebbe essere il 47esimo ma magari prova 46 e 48.

Nel file Keyboard.cpp trovi la famigerata tabella e quelli a destra sono i caratteri che escono fuori ma a sinistra non c'è il valore che devi usare nella write ma il valore che verrà effettivamente mandato (ma che tu non puoi stabilire) e tu, per selezionarlo, devi devere in che posizione sta.

Spero di essermi spiegato.

Massimiliano_Dolcini:
Keyboard.write(0x38)
che dovrebbe corrispondere a "/" , salta fuori "8" che sarebbe 0x25.

Scusa, ma intanto prima parlavamo della print() di stringhe, ora parli di write() di caratteri, ma a parte questo credo che tu stia facendo sempre una grossa confusione tra scancode, codici ascii US e italiani, oltre a confondere valori decimali con quelli esadecimali... E forse stai continuando anche a vedere il file Keyboard.cpp originale e non la modifica con l'array italianoche ti ho postato per i valori dell'array _asciimap[].

Per dire, chi lo ha detto che 0x38 corrisponde a '/'? Il valore esadecimale 0x38 corrisponde al valore decimale 56, quindi dato che _asciimap[56] corrisponde al tasto "8" ed il codice ASCII del carattere '8' è proprio 56, sul PC hai giustamente il carattere "8"!

Il carattere '/' ha il codice ASCII 47 e sulla tastiera italiana è sul tasto 7, quindi con lo shift: infatti nella tabella che ti ho postato se lo cerchi lo trovi in posizione 47 dell'array (in esadecimale 0x2F) definito come "0x24 | SHIFT". Quindi per avere il carattere '/' usando la write() devi usare:

Keyboard.write(0x2F);
o
Keyboard.write(47);
o
Keyboard.write('/');
oppure
Keyboard.print("/");

Che tu stia continuando a vedere la tabella originale di Keyboard.cpp è provato anche dal tuo discorso sul carattere '?' (abituati ad usare sempre i singoli apici quando parli di caratteri... :wink: )...
Vero che l'ASCII di '?' è 63, e tu dici che:
nel file Keyboard.cpp corrisponde ">" (0x37|SHIFT), ma alla fine viene mostrato "_"

Infatti nell'array italiano che ti ho postato se vedi hai in posizione 63 il valore "0x2d|SHIFT" e non "0x37|SHIFT".

Insomma, fai come ti ho consigliato, copia da qualche parte il file Keyboard.cpp originario (che so, chiamalo "Keyboard-ORIG.cpp") e modifica il suo contenuto nella parte dove si definisce l'array _asciimap[], ricompila e vedi se funziona. Come detto, quell'array l'ho solo trovato e più o meno mi corrisponde, ma fai tu le tue prove ulteriori per sicurezza.

Il carattere '>' dovrebbe essere il 62esimo, 0x3E in esadecimale

Noto che nella tabella mancano tutte le accentate e ci sono già 128 caratteri.

O si cambiano i primi non stampabili (che nella tabella hanno il valore 0x00) oppure andrebbe rifatta la libreria.

Oppure si adatta, estendendola all'architettura AVR quella esistente per la Teensy che emula le tastiere nazionali, credo sarebbe la soluzione migliore.

zoomx:
Il carattere '>' dovrebbe essere il 62esimo, 0x3E in esadecimale

Si, esatto, e non è mappato (0x00), infatti avevo scritto che l'array "italiano" non è del tutto completo.
Bisogna trovare lo scancode del tasto che nella tastiera italiana si trova a sinistra della "Z" e mettere al posto di 0x00 il corrispondente valore.

Noto che nella tabella mancano tutte le accentate e ci sono già 128 caratteri.

Certo, perché le accentate sono parte del cosiddetto "ASCII esteso" con i valori maggiori di 127. Bisognerebbe modificare quell'array per portarlo a 256 elementi, e provare a rimappare (sempre lo scancode) almeno i caratteri accentati, ma questo significa modificare la libreria Keyboard, non solo cambiare dei valori...

O si cambiano i primi non stampabili (che nella tabella hanno il valore 0x00) oppure andrebbe rifatta la libreria.

Bisognerebbe però rimappare i valori maggiori di 127 con i primi 28 (31 meno i 3 già mappati), comunque sempre una modifica della libreria.

Oppure si adatta, estendendola all'architettura AVR quella esistente per la Teensy che emula le tastiere nazionali, credo sarebbe la soluzione migliore.

Bah. Per me si fa prima a lasciare tutto com'è ed impostare come "US Standard" la "tastiera" che Arduino fa vedere al sistema operativo...

Secondo quanto scritto qui

il carattere '>' nella tastiera italiana dovrebbe essere 0x56|SHIFT
mentre solo 0x56 per il '<'

Credo sia corretto, basta mettere quei valori nell'array nelle posizioni corrispondenti.

Scusate veramente, non so cosa dire, sarò io che non capisco, però, e faccio come hai detto te:

Keyboard.write(0x2F);
o
Keyboard.write(47);
o
Keyboard.write('/');
oppure
Keyboard.print("/");

Mi da sempre il carattere sbagliato, se uso il ragionamento che mi avete detto di usare ovvero che:

Keyboard.write(0x3e);
0x3e=62
asciimap[62]=>

In output ricevo sempre un carattere differente.
Magari ho nuovamente capito male io, altrimenti non so...

Massimiliano_Dolcini:
Scusate veramente, non so cosa dire, sarò io che non capisco, però, e faccio come hai detto te:
Mi da sempre il carattere sbagliato

Ripeto, ma tu hai modificato keyboard.cpp mettendo l'array con la mappatura "italiana" o no?

E quando dici che ricevi sempre un carattere differente, mi fai un esempio di ciò che scrivi su Arduino con la Keyboard.write() e cosa invece ottieni (es. "scrivo x ed esce y, poi scrivo z ed esce k")?

E, in sostanza, fare la cosa più semplice (lasciare la keyboard.cpp come sta, e su Windows impostare quella tastiera come "US Standard") non ti va bene?

Se non modifichi la libreria credo succeda questo
tu metti
Keyboard.write('/');
che è equivalente a
Keyboard.write(0x2F);
alla libreria arriva il valore 0x2F, stabilisce che è un carattere stampabile e quindi cerca lo scancode nella sua tabella e il problema sta qui, lo scancode che trova è quello della tastiera US che è differente da quello della tastiera italiana. Questo perché lo scancode fa riferimento al tasto che premi e non al carattere che c'è scritto sopra.
Per questo si dovrebbe cambiare la tabella. La seccatura è però che se si aggiorna il core (il compilatore, non l'IDE) il cambiamento va perso.
Purtroppo mi pare che la libreria non permetta l'invio diretto dello scancode.

Su github è stato aperto un issue pochi giorni fa per il supporto delle tastiere internazionali

e ci sono anche issue riguardanti l'impossibilità di stampare alcuni caratteri.

Ho cercato su Github librerie alternative ma fino adesso non ne ho trovate.

Edit:
volevo provare a modificare la tabella. Arrivato ai numeri trovo in tabella questi valori
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
che però son diversi dagli scancodes che trovo qui

0 in tabella ha lo scancodes 0x27 che però, secondo il link sopra, è assegnato a un tasto a sinistra dell'invio mentre lo scancodes dovrebbe essere 0x0B

Edit2:
sembrerebbe che gli scancodes che si trovano su kbdlayout.info non siano attendibili ma ci deve essere una spiegazione. Il problema è trovare scancodes corretti per la tastiera italiana.

Edit3:
Forse quegli scancodes erano per le tastiere PS/2 mentre ci sono degli scancodes diversi per le tastiere USB-HID. Chissà perché poi.

Qui

una bella discussione in merito alle librerie per capire come fare ma è l'ultimo messaggio quello importante: una libreria che gestisce più tastiere, ancora non provata.

Per me resta più semplice definire il tipo di tastiera direttamente su Windows, e ci pensa poi lui, comunque in rete ho trovato anche questa lista di codici che vedete sotto, che sembrerebbe proprio relativa a USB HID. Tenendo presente la posizione dei tasti US si dovrebbe con questo capire meglio come modificare Keyboard.cpp per implementare una tastiera italiana.
In ogni caso teniamo d'occhio QUESTO issue thread relativo alla keyboard... :wink:

	0x00	Reserved (no event indicated)
	0x01	Keyboard ErrorRollOver
	0x02	Keyboard POSTFail
	0x03	Keyboard ErrorUndefined
	0x04	Keyboard a and A
	0x05	Keyboard b and B
	0x06	Keyboard c and C
	0x07	Keyboard d and D
	0x08	Keyboard e and E
	0x09	Keyboard f and F
	0x0A	Keyboard g and G
	0x0B	Keyboard h and H
	0x0C	Keyboard i and I
	0x0D	Keyboard j and J
	0x0E	Keyboard k and K
	0x0F	Keyboard l and L
	0x10	Keyboard m and M
	0x11	Keyboard n and N
	0x12	Keyboard o and O
	0x13	Keyboard p and P
	0x14	Keyboard q and Q
	0x15	Keyboard r and R
	0x16	Keyboard s and S
	0x17	Keyboard t and T
	0x18	Keyboard u and U
	0x19	Keyboard v and V
	0x1A	Keyboard w and W
	0x1B	Keyboard x and X
	0x1C	Keyboard y and Y
	0x1D	Keyboard z and Z
	0x1E	Keyboard 1 and !
	0x1F	Keyboard 2 and @
	0x20	Keyboard 3 and #
	0x21	Keyboard 4 and $
	0x22	Keyboard 5 and %
	0x23	Keyboard 6 and ^
	0x24	Keyboard 7 and &
	0x25	Keyboard 8 and *
	0x26	Keyboard 9 and (
	0x27	Keyboard 0 and )
	0x28	Keyboard Return (ENTER)
	0x29	Keyboard ESCAPE
	0x2A	Keyboard DELETE (Backspace)
	0x2B	Keyboard Tab
	0x2C	Keyboard Spacebar
	0x2D	Keyboard - and (underscore)
	0x2E	Keyboard = and +
	0x2F	Keyboard [ and {
	0x30	Keyboard ] and }
	0x31	Keyboard \ and |
	0x32	Keyboard Non-US # and ~
	0x33	Keyboard ; and :
	0x34	Keyboard ' and "
	0x35	Keyboard Grave Accent and Tilde
	0x36	Keyboard, and <
	0x37	Keyboard . and >
	0x38	Keyboard / and ?
	0x39	Keyboard Caps Lock
	0x3A	Keyboard F1
	0x3B	Keyboard F2
	0x3C	Keyboard F3
	0x3D	Keyboard F4
	0x3E	Keyboard F5
	0x3F	Keyboard F6
	0x40	Keyboard F7
	0x41	Keyboard F8
	0x42	Keyboard F9
	0x43	Keyboard F10
	0x44	Keyboard F11
	0x45	Keyboard F12
	0x46	Keyboard PrintScreen
	0x47	Keyboard Scroll Lock
	0x48	Keyboard Pause
	0x49	Keyboard Insert
	0x4A	Keyboard Home
	0x4B	Keyboard PageUp
	0x4C	Keyboard Delete Forward
	0x4D	Keyboard End
	0x4E	Keyboard PageDown
	0x4F	Keyboard RightArrow
	0x50	Keyboard LeftArrow
	0x51	Keyboard DownArrow
	0x52	Keyboard UpArrow
	0x53	Keypad Num Lock and Clear
	0x54	Keypad /
	0x55	Keypad *
	0x56	Keypad -
	0x57	Keypad +
	0x58	Keypad ENTER
	0x59	Keypad 1 and End
	0x5A	Keypad 2 and Down Arrow
	0x5B	Keypad 3 and PageDn
	0x5C	Keypad 4 and Left Arrow
	0x5D	Keypad 5
	0x5E	Keypad 6 and Right Arrow
	0x5F	Keypad 7 and Home
	0x60	Keypad 8 and Up Arrow
	0x61	Keypad 9 and PageUp
	0x62	Keypad 0 and Insert
	0x63	Keypad . and Delete
	0x64	Keyboard Non-US \ and |
	0x65	Keyboard Application
	0x66	Keyboard Power
	0x67	Keypad =
	0x68	Keyboard F13
	0x69	Keyboard F14
	0x6A	Keyboard F15
	0x6B	Keyboard F16
	0x6C	Keyboard F17
	0x6D	Keyboard F18
	0x6E	Keyboard F19
	0x6F	Keyboard F20
	0x70	Keyboard F21
	0x71	Keyboard F22
	0x72	Keyboard F23
	0x73	Keyboard F24
	0x74	Keyboard Execute
	0x75	Keyboard Help
	0x76	Keyboard Menu
	0x77	Keyboard Select
	0x78	Keyboard Stop
	0x79	Keyboard Again
	0x7A	Keyboard Undo
	0x7B	Keyboard Cut
	0x7C	Keyboard Copy
	0x7D	Keyboard Paste
	0x7E	Keyboard Find
	0x7F	Keyboard Mute
	0x80	Keyboard Volume Up
	0x81	Keyboard Volume Down
	0x82	Keyboard Locking Caps Lock
	0x83	Keyboard Locking Num Lock
	0x84	Keyboard Locking Scroll Lock
	0x85	Keypad Comma
	0x86	Keypad Equal Sign
	0x87	Keyboard International1
	0x88	Keyboard International2
	0x89	Keyboard International3
	0x8A	Keyboard International4
	0x8B	Keyboard International5
	0x8C	Keyboard International6
	0x8D	Keyboard International7
	0x8E	Keyboard International8
	0x8F	Keyboard International9
	0x90	Keyboard LANG1
	0x91	Keyboard LANG2
	0x92	Keyboard LANG3
	0x93	Keyboard LANG4
	0x94	Keyboard LANG5
	0x95	Keyboard LANG6
	0x96	Keyboard LANG7
	0x97	Keyboard LANG8
	0x98	Keyboard LANG9
	0x99	Keyboard Alternate Erase
	0x9A	Keyboard SysReq/Attention
	0x9B	Keyboard Cancel
	0x9C	Keyboard Clear
	0x9D	Keyboard Prior
	0x9E	Keyboard Return
	0x9F	Keyboard Separator
	0xA0	Keyboard Out
	0xA1	Keyboard Oper
	0xA2	Keyboard Clear/Again
	0xA3	Keyboard CrSel/Props
	0xA4	Keyboard ExSel
	0xE0	Keyboard LeftControl
	0xE1	Keyboard LeftShift
	0xE2	Keyboard LeftAlt
	0xE3	Keyboard Left GUI
	0xE4	Keyboard RightControl
	0xE5	Keyboard RightShift
	0xE6	Keyboard RightAlt
	0xE7	Keyboard Right GUI

zoomx:
una libreria che gestisce più tastiere, ancora non provata.

Si, l'avevo già vista ma non c'è la tastiera italiana...

L'italiano c'era scritto nella descrizione ma il file non c'è.
Leggendo qui

sembra però che generarlo non sia difficile.

Ho trovato gli scancodes ma sono tutti per la tastiera US, anche il documento USB-HID ufficiale