Ako na konfiguráciu herných ovládačov 2.

Ako na konfiguráciu herných ovládačov 2.
23.12.2018 17:30 | Články | mirek biňas

V minulom článku sme si ukázali, ako jednoducho je možné pripojiť aj takmer neznámy herný ovládač k Linuxu a začať ho okamžite používať v hernom klientovi Steam. Dnes si však spravíme jemnú odbočku a pokúsime sa uspokojiť aj tých náročnejších používateľov, ktorí sa až tak často nehrajú. Dnes sa totiž pozrieme na to, ako pracuje linuxový vstupno/výstupný podsystém.

Linuxový vstupno/výstupný podsystém

Vstupno/výstupný podsystém (z angl. the input subsystem) je časťou linuxového jadra. Stará sa o rozličné vstupné zariadenia, akými sú napr. klávesnice, myši, herné ovládače a pod., ktoré používateľ používa na interakciu s operačným systémom a jeho aplikáciami. Tieto zariadenia sú k systému pripojené prostredníctvom rozličných komunikačných rozhraní, ako napr. sériový port, PS/2, USB, a pod., ktoré sú taktiež spravované pomocou jadra. Jadro taktiež zabezpečuje jednotný a od zariadení nezávislý spôsob, ako informáciu zo vstupného zariadenia prenesie do používateľského priestoru (z angl. user space).

Poznámka: Vzhľadom na anglický termín The Input Subsystem by preklad mal znieť skôr vstupný podsystém. Keďže ale je možné s pripojenými zariadeniami komunikovať obojsmerne, budem v článku používať slovenský preklad vstupno/výstupný podsystém alebo skrátene len V/V podsystém.

Spracovanie vstupu

Predtým, ako sa bližšie pozrieme na samotný linuxový vstupno/výstupný podsystém, sa pozrieme na to, ako sa informácia zo vstupného zariadenia dostane až do koncovej aplikácie. Tento prenos si ilustrujeme na bežnej situácii - písanie na klávesnici do terminálu v grafickom prostredí systému.

+------------+               +----------------+             +----------+ 
| klávesnica |-------------->| základná doska |------------>| procesor |
+------------+               +----------------+             +----------+ 
              dátová zbernica                 dátová zbernica

Obrázok 1: Schéma komunikácie od klávesnice k procesoru (zdroj)

Klávesnica je k počítaču pripojená k niektorému z dostupných komunikačných portov. Dnes sa v prípade externých klávesníc jedná najčastejšie o port USB, ale nemusí to byť jediná možnosť. Informácia o stlačení alebo uvoľnení klávesy sa následne prostredníctvom tejto komunikačnej zbernice prenáša do počítača, kde procesor vyvolá prerušenie.

         +-------+        +----------+          +-----------+ 
-------->| jadro |------->| X server |--------->| aplikácia |
         +-------+        +----------+          +-----------+
prerušenie

Obrázok 2: Spracovanie udalosti (prerušenia) jadrom a jej doručenie do aplikácie (zdroj)

Prerušenie vyvolané procesorom je následne ošetrené v jadre operačného systému. Tu dôjde k identifikácii typu udalosti (stlačenie alebo uvoľnenie klávesy) a rovnako dôjde k zisteniu hodnoty stlačenej klávesy, ktorá sa označuje ako scancode. Jadro následne scancode premapuje na tzv. keycode a informáciu o tejto udalosti zapíše do súboru, ktorý reprezentuje zariadenie klávesnice (napr. /dev/input/event3). Tým sa informácia o vzniknutej udalosti dostala z priestoru jadra do používateľského priestoru, kde sa k nej vedia dostať samotné aplikácie.

X server sa o vzniknutej udalosti dozvie práve po prečítaní obsahu tohto súboru.

Linuxový vstupno/výstupný podsystém pod kapotou

Teraz sa pozrime na opísané správanie podrobnejšie. Na obrázku 3 je zobrazený princíp fungovania linuxového vstupno/výstupného podsystému. Prerušovanými čiarami je táto schéma rozdelená na tri časti. Tá najspodnejšia je označená ako Hardware (hardvér). Je to časť, ktorá znázorňuje (a reprezentuje) pripojené zariadenia k počítaču komunikujúce pomocou rozličných technológií a zberníc. S týmito zariadeniami komunikuje jadro pomocou špecifických modulov v prostrednej časti, ktorá sa nazýva Kernel Space (priestor jadra). Tento priestor je však pre používateľa uzavretý a preto jadro potrebuje vhodným spôsobom informácie od vstupných zariadení dostať do aplikácií, s ktorými pracuje používateľ. Tieto sú spustené v tretej hornej časti obrázku s názvom User Space (používateľský priestor).

Bloková schéma vstupného podsystému linuxového jadra

Obrázok 3: Bloková schéma vstupného podsystému linuxového jadra (zdroj)

Srdcom celého vstupno/výstupného podsystému je modul input-core (na obrázku je zobrazený pod menom Input Core). Tento musí byť zavedený pred zavedením akýchkoľvek ďalších modulov spolupracujúcich so V/V podsystémom. V súčasných moderných distribúciách je tento modul statickou súčasťou jadra, takže ho nenájdete v zozname zavedených modulov pomocou príkazu lsmod.

Ďalšie moduly V/V systému delíme do dvoch kategórií, ktoré spolu úzko spolupracujú:

  1. ovládače zariadení (input device drivers)
  2. ovládače udalostí (input event drivers)

Ovládače zariadení komunikujú so vstupnými zariadeniami na tej najnižšej úrovni. Ich hlavnou úlohou je predať informáciu o tom, k akej udalosti došlo na pripojenom zariadení z priestoru jadra do používateľského priestoru. Čo je však veľmi dôležité, tieto informácie sa musia odovzdať vo forme, ktorej bude rozumieť každý modul V/V ekosystému. Táto "zrozumiteľná" forma sa volá evdev.

Aby bolo možné v používateľskom priestore čítať údaje z pripojených zariadení, je pre každé zariadenie v priečinku /dev/input/ vytvorený špeciálny súbor typu character device (pri dlhom výpise pomocou príkazu ls -l ho spoznáte podľa toho, že prvý znak, ktorý určuje typ súboru, je písmeno 'c'). Ak na príslušnom zariadení vznikne udalosť, je táto zapísaná do tohto súboru. Následné získavanie informácií o vzniknutej udalosti neznamená nič viac, ako prečítanie správy z príslušného súboru vo formáte evdev API.

Poznámka: Tento prístup plne zodpovedá jednej zo základných vlastností unix-ových operačných systémov, ktorá hovorí, že "všetko je súbor".

Pozrime sa teda na praktický príklad, ako celý tento mechanizmus pracuje. Pri bežnej práci s počítačom štandardne používame dve vstupné zariadenia - klávesnicu a myš. Pri zavádzaní systému alebo neskôr, keď už systém beží a používateľ tieto zariadenia pripojí, dôjde k rozpoznaniu týchto vstupných zariadení, následne k zavedeniu príslušných ovládačov jadra a vytvoreniu príslušných súborov, ktoré tieto zariadenia reprezentujú v priečinku /dev/input/. Ak sa pozriete do tohto priečinku, uvidíte v ňom niekoľko súborov s prefixom eventX. Ako však identifikovať, ktoré z nich reprezentujú klávesnicu a ktoré myš?

Zoznam dostupných vstupných zariadení

Zoznam aktuálne dostupných zariadení vieme získať niekoľkými spôsobmi. Miesto vypisovania obsahu priečinku /dev/input/ alebo vypisovania obsahu súboru /proc/bus/input/devices však použijeme príkaz evtest, ktorý slúži práve na monitorovanie činnosti udalostí na pripojených zariadeniach. Tento nástroj však nie je súčasťou štandardnej inštalácie vašej distribúcie a musíte si ho doinštalovať ručne. V prípade distribúcie Fedora nainštalujte balíček evtest takto:

$ sudo dnf install evtest

Pokiaľ spustíte tento nástroj bez akýchkoľvek parametrov ako bežný používateľ, na obrazovke terminálu sa vám zobrazí zoznam aktuálne pripojených zariadení. Ako bežnému používateľovi sa vám však nemusí zobraziť žiadne zariadenie. Preto tento nástroj radšej spúšťajte s právami superpoužívateľa.

Každý záznam zoznamu pripojených zariadení, ktorý vypísal nástroj evtest, sa skladá z dvoch položiek: zo súboru reprezentujúceho toto zariadenie, a z názvu príslušného zariadenia. Týmto spôsobom je potom veľmi jednoduché zistiť, ktorý súbor reprezentuje príslušné vstupné zariadenie:

$ sudo evtest 
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:    Lid Switch
/dev/input/event1:    Sleep Button
/dev/input/event2:    Power Button
/dev/input/event3:    AT Translated Set 2 keyboard
/dev/input/event5:    SynPS/2 Synaptics TouchPad
/dev/input/event6:    Video Bus
/dev/input/event7:    Video Bus
/dev/input/event8:    TPPS/2 IBM TrackPoint
/dev/input/event9:    ThinkPad Extra Buttons
/dev/input/event10:    HDA Intel HDMI HDMI/DP,pcm=3
/dev/input/event11:    HDA Intel HDMI HDMI/DP,pcm=7
/dev/input/event12:    HDA Intel HDMI HDMI/DP,pcm=8
/dev/input/event13:    HDA Intel PCH Dock Mic
/dev/input/event14:    HDA Intel PCH Mic
/dev/input/event15:    HDA Intel PCH Dock Headphone
/dev/input/event16:    HDA Intel PCH Headphone
/dev/input/event17:    Integrated Camera
/dev/input/event20:    hongjingda HJD-X
Select the device event number [0-20]: 

Nástroj evtest sa však neukončí a čaká na zadanie čísla vstupného zariadenia, ktorého udalosti je možné monitorovať. Ak číslo zariadenia zadáte, evtest začne dané zariadenie monitorovať a vypisovať udalosti, ku ktorým na zariadení dochádza v reálnom čase.

Pozrime sa však na výstup, ktorý sme získali. Podľa neho je moja klávesnica reprezentovaná pomocou zariadenia (resp. súboru) event3. K laptopu aktuálne nemám pripojenú externú myš, za to touchpad je reprezentovaný zariadením event5 a TrackPoint zariadením event8. V zoznam sa rovnako nachádza aj prijímač pre môj herný ovládač ako zariadenie event20.

Monitorovanie udalostí vstupných zariadení

V minulej časti seriálu sme testovali to, či pri manipulácii so zariadením dochádza k vyvolaniu nejakých udalostí jednoduchým výpisom obsahu príslušného súboru zariadenia pomocou príkazu cat. To, čo ste videli na obrazovke, boli správy komunikačného rozhrania evdev API, ktoré sú "zabalené" v štruktúre input_event (jej definícia sa nachádza v súbore include/linux/input.h).

Tento výstup však nebol veľmi zrozumiteľný. Miesto toho, aby ste si vytvorili vlastný monitor pomocou niektorej z knižníc pre váš najobľúbenejší programovací jazyk, môžete s výhodou použiť práve nástroj evtest, ktorého hlavnou úlohou je práve monitorovanie pripojených zariadení.

Monitorovací režim príslušného zariadenia je možné spustiť dvoma spôsobmi - buď nástroj spustíte bez parametrov a vyberiete si číslo príslušného zariadenia (číslo v postfixe súboru /dev/input/eventX) alebo nástroj spustíte priamo s uvedením cesty k súboru zariadenia, ktoré chcete monitorovať. Ak chcem v mojom prípade monitorovať udalosti zariadenia herného ovládača, ktorý je reprezentovaný súborom /dev/input/event20, nástroj evtest spustím nasledovne:

$ evtest /dev/input/event20

Priamo po spustení evtest vypíše informácie o uvedenom zariadení spolu so zoznamom všetkých udalostí, ktoré zariadenie podporuje. V mojom prípade bude teda výstup príkazu hneď po spustení vyzerať nasledovne:

$ evtest /dev/input/event20 
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x2563 product 0x526 version 0x110
Input device name: "hongjingda HJD-X"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event code 306 (BTN_C)
    Event code 307 (BTN_NORTH)
    Event code 308 (BTN_WEST)
    Event code 309 (BTN_Z)
    Event code 310 (BTN_TL)
    Event code 311 (BTN_TR)
    Event code 312 (BTN_TL2)
    Event code 313 (BTN_TR2)
    Event code 314 (BTN_SELECT)
    Event code 315 (BTN_START)
    Event code 316 (BTN_MODE)
    Event code 317 (BTN_THUMBL)
    Event code 318 (BTN_THUMBR)
    Event code 319 (?)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value    128
      Min        0
      Max      255
      Flat      15
    Event code 1 (ABS_Y)
      Value    127
      Min        0
      Max      255
      Flat      15
    Event code 2 (ABS_Z)
      Value    128
      Min        0
      Max      255
      Flat      15
    Event code 5 (ABS_RZ)
      Value    127
      Min        0
      Max      255
      Flat      15
    Event code 9 (ABS_GAS)
      Value      0
      Min        0
      Max      255
      Flat      15
    Event code 10 (ABS_BRAKE)
      Value      0
      Min        0
      Max      255
      Flat      15
    Event code 16 (ABS_HAT0X)
      Value      0
      Min       -1
      Max        1
    Event code 17 (ABS_HAT0Y)
      Value      0
      Min       -1
      Max        1
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)

Od tohto momentu je nástroj v monitorovacom režime a akákoľvek manipulácia so zariadením sa prejaví zobrazením informácií o vzniknutej udalosti.

Ešte predtým, ako sa však pozrieme na podobu týchto správ, pozrieme sa na to, aké rozličné typy udalostí môže vstupné zariadenie generovať.

Typy vstupných udalostí

V závislosti od typu pripojeného zariadenia sa zoznam podporovaných udalostí môže líšiť. Napr. myš nebude pracovať s udalosťami pre rozsvecovanie LED diód. Taktiež nebude prehrávať audio výstup na zabudovanom reproduktore.

Ak sa pozrieme bližšie na typy udalostí, ktoré môžu vzniknúť na mojom pripojenom ovládači, jedná sa konkrétne o tieto štyri udalosti:

  1. EV_SYN - Používa sa ako značkovač, resp. oddeľovač jednotlivých udalostí.
  2. EV_KEY - Udalosť sa používa na opísanie zmeny stavu "klávesových" zariadení, akými sú napr. klávesnica, tlačidlá na ovládači alebo myši.
  3. EV_ABS - Používa sa na opis zmien absolútnych hodnôt v súradnicovom, ako napr. dotyk na dotykovej obrazovke alebo pohyb joystickom.
  4. EV_MSC - Používa sa na opis rôznych iných vstupných údajov, ktoré nie je možné zaradiť do žiadneho iného typu udalostí.

Samozrejme tieto typy udalostí nie sú všetky, ktoré môžu v rozličných zariadeniach vzniknúť. Ak vás zaujímajú všetky typy udalostí, odporúčam sa pozrieť do oficiálnej dokumentácie.

Pozrime sa teda na fragment výpisu udalostí, ktorú zachytí nástroj evtest počas monitorovania:

Event: time 1545515462.520914, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90002
Event: time 1545515462.520914, type 1 (EV_KEY), code 305 (BTN_EAST), value 1
Event: time 1545515462.520914, -------------- SYN_REPORT ------------
Event: time 1545515462.600987, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90002
Event: time 1545515462.600987, type 1 (EV_KEY), code 305 (BTN_EAST), value 0
Event: time 1545515462.600987, -------------- SYN_REPORT ------------

Pokúsme sa analyzovať, k čomu došlo. Opticky dokážeme rozpoznať dve udalosti oddelené udalosťou EV_SYN (vo výstupe označená ako SYN_REPORT).

Prvá udalosť sa skladá z dvoch udalostí. Tou prvou je udalosť EV_MSC (typ udalosti č. 4 - čiže ostatné), v ktorej sa nachádza scancode klávesy, ktorú pošle zariadenie do počítača. V tomto prípade herný ovládač poslal kód 0x90002.

Následne je tento kód namapovaný linuxovým jadrom na keycode v nasledujúcej udalosti EV_KEY, pričom hodnota kódu klávesy je 0x305, čo zodpovedá tlačidlu s označením BTN_EAST. Táto udalosť hovorí o tom, že toto tlačidlo bolo stlačené, čo reprezentuje hodnota 1.

Pri pohľade na druhú udalosť, ktorá sa nachádza v druhom bloku oddelom oddeľovačom udalostí, prídeme na to, že sa v nej nachádzajú rovnaké položky ako v prípade prvej udalosti. V tomto prípade však ide o uvoľnenie tlačidla BTN_EAST, o čom hovorí hodnota 0.

Poznámka: Pomocou nástroja evtest v kombinácii s konfiguráciou udev môžete vytvoriť vlastné mapovanie scancodes na keycodes. To sa hodí napr. vtedy, ak máte zariadenie, ktoré pri stláčaní tlačidiel nevracia očakávané kódy kláves.

Záver

V tomto článku sme sa pozreli bližšie na to, ako vyzerá linuxový vstupno/výstupný podsystém. Nabudúce sa pozrieme na to, ako si pripraviť vlastnú konfiguráciu ovládača. To sa nám zíde, ak hra nie je dostupná cez hernú platformu Steam a tlačidlá ovládača nepracujú v hre podľa očakávania.

Použité zdroje

  1. Play with any USB controller on Linux using xboxdrv to emulate an XBOX controller - http://steamcommunity.com/app/236090/discussions/0/558748653724279774/?insideModal=1
  2. RetroArch Configuration - https://github.com/retropie/retropie-setup/wiki/retroarch-configuration
  3. The 60 seconds delay - https://github.com/xboxdrv/xboxdrv/issues/144
  4. Writing udev rules - http://www.reactivated.net/writing_udev_rules.html
  5. Linux Gamepad API - https://www.kernel.org/doc/Documentation/input/gamepad.txt
  6. Linux input ecosystem - https://joeshaw.org/linux-input-ecosystem/
  7. mauálová stránka príkazu evtest
  8. How do keyboard input and text output work? - http://unix.stackexchange.com/questions/116629/how-do-keyboard-input-and-text-output-work
  9. evdev - https://en.wikipedia.org/wiki/Evdev
  10. The difference between uinput and evdev - http://who-t.blogspot.sk/2016/05/the-difference-between-uinput-and-evdev.html
  11. Input Drivers - http://www.embeddedlinux.org.cn/essentiallinuxdevicedrivers/final/ch07lev1sec1.html
  12. Explain EV in /proc/bus/input/devices data - http://unix.stackexchange.com/questions/74903/explain-ev-in-proc-bus-input-devices-data
  13. Using the Input Subsystem, Part II - http://www.linuxjournal.com/node/6429
  14. event-codes.txt - https://www.kernel.org/doc/Documentation/input/event-codes.txt
  15. Linux Input subsystem – I - https://nutcutkernel.wordpress.com/2015/04/12/linux-input-subsystem/
  16. Howto remap keyboard keys in Linux - https://mohan43u.wordpress.com/2017/05/29/howto-remap-keyboard-keys-in-linux/
  17. Keyboard Input - https://wiki.archlinux.org/index.php/Keyboard_input
    • RE: Ako na konfiguráciu herných ovládačov 2. 23.12.2018 | 23:16
      Avatar bedňa LegacyIce-antiX  Administrátor

      Ani nevieš ako rád som si to prečítal. Píšeš výborne ako vždy a dal som to na ranu.

      Dík kámo a som rád že si späť.

      Prajem ti všetko najlepšie a nie len cez Vianoce.

      Táto správa neobsahuje vírus, pretože nepoužívam MS Windows. http://kernelultras.org
    • RE: Ako na konfiguráciu herných ovládačov 2. 11.02 | 12:28
      Avatar Grex0   Návštevník

      Super, tak ako ma bavili prednášky tak ma bavil článok.