Z tego co pamiętam, klasyczne rozwiązania opierają się na "matrycach" Gdzie rząd jest zrobiony na przerwaniach (hardware interrupts) i np. Rzad klawiszy Q-P jest na jednym, A-L na innym.
Czyli robi się tak ze Q jest pociagniete jednoczesnie do PD0 i PD4 (patrzylem na szybko na pinout arduino micro) klawisz W do PD0 i PC6 itd..
Dzieki przerwaniom masz natychmiastową informacje o tym ze coś zostalo wcisniete, nastepnie sprawdzasz ktora konkretna litera zostala wcisnieta, czytając rejestr.
Debouncing jest czesto realizowany filtrami RC (rezystor kondesantor) dzieki czemu unika się tzw. drgania stykow, ktore mogą sie przytrafić przy wciśnięciu.
No i teraz, najwieksza zabawa czyli jak już poprawnie skomponujesz po stronie mikrokontrolera co zostało wcisnięte nalezy wyslać odpowiednią ramkę deskryptora USB.
Pamietam ze mozna znaleźć w necie gotowce które symulują gamepada/joystick.
Wtedy jedyne co musisz zrobić to zmapować swoje przyciski na wysyłane dane.
Z USB to mniej więcej tak robiłem z 10 lat temu, jak zrobiłem na STM32 bieda wersję DIY gitary do guitar hero :D