Site : tvaira.free.fr

Tests

Préparation

On pourra installer les paquets suivants :

$ apt-cache show joystick
...
Description-fr: série de tests et outils de calibration pour manette de jeu
 Some useful tools for using joysticks:
  evdev-joystick(1) - joystick calibration tool
  ffcfstress(1)     - force-feedback stress test
  ffmvforce(1)      - force-feedback orientation test
  ffset(1)          - force-feedback configuration tool
  fftest(1)         - general force-feedback test
  jstest(1)         - joystick test
  jscal(1)          - joystick calibration tool
...
$ sudo apt-get install joystick

$ apt-cache show input-utils
...
Description-fr: utilitaire pour la couche de saisie du noyau Linux
 Ce paquet fournit un ensemble d'utilitaires destinés à utiliser la couche
 de saisie (« input layer ») du noyau Linux (version 2.6 et ultérieures).
 Cela inclut des utilitaires permettant d'afficher les périphériques de
 saisie et interroger ou modifier les cartes du clavier.
...
$ sudo apt install input-utils

Les contrôleurs PlayStation auront probablement besoin du paquet xboxdrv :

$ sudo apt-get install xboxdrv

Manche à balai MaxFighter F-23

  • Détection : brancher le joystick
$ dmesg
...
[79210.353243] usb 1-1: New USB device found, idVendor=0458, idProduct=1004
[79210.353244] usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[79210.353245] usb 1-1: Product: 4-axis 8-button joystick
[79210.357301] input: 4-axis 8-button joystick as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:0458:1004.0004/input/input16
[79210.357461] hid-generic 0003:0458:1004.0004: input,hidraw3: USB HID v1.10 Joystick [4-axis 8-button joystick] on usb-0000:00:14.0-1/input0

$ lsusb
...
Bus 001 Device 053: ID 0458:1004 KYE Systems Corp. (Mouse Systems) Flight2000 F-23 Joystick

$ sudo lsinput
...
/dev/input/event16
   bustype : BUS_USB
   vendor  : 0x458
   product : 0x1004
   version : 272
   name    : "4-axis 8-button joystick"
   phys    : "usb-0000:00:14.0-1/input0"
   uniq    : ""
   bits ev : (null) (null) (null) (null)
  • Test :
$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (4-axis 8-button joystick) has 6 axes (X, Y, Rz, Throttle, Hat0X, Hat0Y)
and 8 buttons (Trigger, ThumbBtn, ThumbBtn2, TopBtn, TopBtn2, PinkieBtn, BaseBtn, BaseBtn2).
Testing ... (interrupt to exit)
Axes:  0:     0  1:     0  2:-18580  3:-32431  4:     0  5:     0 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off
Ctrl-C

$ evtest /dev/input/event16
...
Event: time 1543044483.292313, -------------- SYN_REPORT ------------
Event: time 1543044483.300312, type 3 (EV_ABS), code 0 (ABS_X), value 131
Event: time 1543044483.300312, -------------- SYN_REPORT ------------
Event: time 1543044483.940278, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90002
Event: time 1543044483.940278, type 1 (EV_KEY), code 289 (BTN_THUMB), value 1
Event: time 1543044483.940278, -------------- SYN_REPORT ------------
Event: time 1543044484.156265, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90002
Event: time 1543044484.156265, type 1 (EV_KEY), code 289 (BTN_THUMB), value 0
Event: time 1543044484.156265, -------------- SYN_REPORT ------------

Manette Sony PlayStation

  • Détection : brancher la manette
$ dmesg
[79458.204821] usb 1-1: New USB device found, idVendor=054c, idProduct=0268
[79458.204823] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[79458.204824] usb 1-1: Product: PLAYSTATION(R)3 Controller
[79458.204825] usb 1-1: Manufacturer: Sony
[79458.245637] input: Sony PLAYSTATION(R)3 Controller Motion Sensors as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:054C:0268.0005/input/input18
[79458.303036] input: Sony PLAYSTATION(R)3 Controller as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:054C:0268.0005/input/input17
[79458.303157] sony 0003:054C:0268.0005: input,hiddev1,hidraw3: USB HID v81.11 Joystick [Sony PLAYSTATION(R)3 Controller] on usb-0000:00:14.0-1/input0
...

$ lsusb
...
Bus 001 Device 054: ID 054c:0268 Sony Corp. Batoh Device / PlayStation 3 Controller

$ sudo lsinput
...
/dev/input/event17
   bustype : BUS_USB
   vendor  : 0x54c
   product : 0x268
   version : 33041
   name    : "Sony PLAYSTATION(R)3 Controller"
   phys    : "usb-0000:00:14.0-1/input0"
   uniq    : "08:a9:5a:8b:27:2d"
   bits ev : (null) (null) (null) (null) (null)
  • Test :
$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Sony PLAYSTATION(R)3 Controller) has 6 axes (X, Y, Z, Rx, Ry, Rz)
and 17 buttons (BtnA, BtnB, BtnX, BtnY, BtnTL, BtnTR, BtnTL2, BtnTR2, BtnSelect, BtnStart, BtnMode, BtnThumbL, BtnThumbR, (null), (null), (null), (null)).
Testing ... (interrupt to exit)
Axes:  0:-19932  1:     0  2:-32767  3:     0  4:     0  5:-32767 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off  8:off  9:off 10:off 11:off 12:off 13:off Axes:  0: -7770  1:     0  2:-32767  3:     0  4:     0  5:-32767 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off  8:off  9:off 10:off 11:off 12:off 13:off Axes:  0:     0  1:     0  2:-32767  3:     0  4:     0  5:-32767 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off  8:off  9:off 10:off 11:off 12:off 13:off

$ evtest /dev/input/event17
...
Event: time 1543045995.405225, -------------- SYN_REPORT ------------
Event: time 1543045995.525221, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90010
Event: time 1543045995.525221, type 1 (EV_KEY), code 308 (BTN_WEST), value 0
Event: time 1543045995.525221, -------------- SYN_REPORT ------------
Event: time 1543045996.145191, type 3 (EV_ABS), code 1 (ABS_Y), value 120
Event: time 1543045996.145191, -------------- SYN_REPORT ------------
Event: time 1543045996.155183, type 3 (EV_ABS), code 1 (ABS_Y), value 119
Event: time 1543045996.155183, -------------- SYN_REPORT ------------

$ xboxdrv
xboxdrv 0.8.8 - http://pingus.seul.org/~grumbel/xboxdrv/ 
Copyright © 2008-2011 Ingo Ruhnke <grumbel@gmail.com> 
Licensed under GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This program comes with ABSOLUTELY NO WARRANTY. 
This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details. 

Controller:        PLAYSTATION(R)3 Controller
Vendor/Product:    054c:0268
USB Path:          001:043
Controller Type:   Playstation 3 USB

$ sudo xboxdrv -L
 id | wid | idVendor | idProduct | Name
----+-----+----------+-----------+--------------------------------------
  0 |   0 |   0x054c |    0x0268 | PLAYSTATION(R)3 Controller

$ sudo xboxdrv --detach-kernel-driver --mimic-xpad
X1:132 Y1:119  X2:121 Y2:126  du:  0 dd:  0 dl:  0 dr:  0  select:0 ps:0 start:0  L3:0 R3:0  /\:  0 O:  0 X:  0 []:  0  L1:  0 R1:  0  L2:  0 R2:  0
X1:132 Y1:119  X2:121 Y2:126  du:  0 dd:  0 dl:  0 dr:  0  select:0 ps:0 start:0  L3:0 R3:0  /\:  0 O:  0 X:  0 []:  0  L1:  0 R1:  0  L2:  0 R2:  0
X1:132 Y1:119  X2:121 Y2:126  du:  0 dd:  0 dl:  0 dr:  0  select:0 ps:0 start:0  L3:0 R3:0  /\:  0 O:  0 X:  0 []:  0  L1:  0 R1:  0  L2:  0 R2:  0
...

# Mode silencieux : -s
$ sudo xboxdrv --detach-kernel-driver --mimic-xpad -s
xboxdrv 0.8.8 - http://pingus.seul.org/~grumbel/xboxdrv/ 
Copyright © 2008-2011 Ingo Ruhnke <grumbel@gmail.com> 
Licensed under GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This program comes with ABSOLUTELY NO WARRANTY. 
This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details. 

Controller:        PLAYSTATION(R)3 Controller
Vendor/Product:    054c:0268
USB Path:          001:043
Controller Type:   Playstation 3 USB

Your Xbox/Xbox360 controller should now be available as:
  /dev/input/js0
  /dev/input/event16

Press Ctrl-C to quit

Logitech Dual Action

Lien : support.logitech.com

  • Détection : brancher la manette
$ dmesg 
...
[376034.938087] usb 1-1: USB disconnect, device number 66
[379814.452462] usb 1-1: new low-speed USB device number 67 using xhci_hcd
[379814.615112] usb 1-1: New USB device found, idVendor=046d, idProduct=c216
[379814.615113] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[379814.615114] usb 1-1: Product: Logitech Dual Action
[379814.615115] usb 1-1: Manufacturer: Logitech
[379814.651504] input: Logitech Logitech Dual Action as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:046D:C216.0013/input/input48
[379814.651587] logitech 0003:046D:C216.0013: input,hidraw4: USB HID v1.10 Joystick [Logitech Logitech Dual Action] on usb-0000:00:14.0-1/input0

$ lsusb
...
Bus 001 Device 067: ID 046d:c216 Logitech, Inc. Dual Action Gamepad

$ sudo lsinput
...
/dev/input/event16
   bustype : BUS_USB
   vendor  : 0x46d
   product : 0xc216
   version : 272
   name    : "Logitech Logitech Dual Action"
   phys    : "usb-0000:00:14.0-1/input0"
   uniq    : ""
   bits ev : (null) (null) (null) (null)
  • Test :
$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Logitech Logitech Dual Action) has 6 axes (X, Y, Z, Rz, Hat0X, Hat0Y)
and 12 buttons (Trigger, ThumbBtn, ThumbBtn2, TopBtn, TopBtn2, PinkieBtn, BaseBtn, BaseBtn2, BaseBtn3, BaseBtn4, BaseBtn5, BaseBtn6).
Testing ... (interrupt to exit)
Axes:  0:     0  1:     0  2:     0  3:     0  4:     0  5:     0 Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off  8:off  9:off 10:off 11:off
Ctrl-C

$ evtest /dev/input/event16
...
Event: time 1543134294.221377, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 1543134294.221377, type 1 (EV_KEY), code 288 (BTN_TRIGGER), value 1
Event: time 1543134294.221377, -------------- SYN_REPORT ------------
Event: time 1543134294.277372, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 1543134294.277372, type 1 (EV_KEY), code 288 (BTN_TRIGGER), value 0
Event: time 1543134294.277372, -------------- SYN_REPORT ------------

Prise en charge sous Qt

Depuis Qt 5.7, on dispose du nouveau module Qt Gamepad qui assure la prise en charge des manettes de jeu directement depuis Qt. Le module fournit les interfaces QML et C++.

Les plateformes suivantes sont supportées :

  • Windows (Win32 via XInput 1.3 & 1.4)
  • Linux (evdev et SDL2)
  • Android
  • macOS, iOS, tvOS

Ce module fournit des classes permettant :

  • de lire les événements d’entrée des manettes (Boutons et Axes),
  • de gérer ces événements à la fois en C++ et en QML,
  • de fournir une configuration de base de la disposition de la manette de jeu, et
  • de générer éventuellement les événements de touche et de souris

Pour utiliser le module Qt Gamepad, il faudra modifier son fichier de projet .pro :

QT += gamepad

On accède ensuite aux classes à partir du fichier d’en-tête QtGamepad :

#include <QtGamepad>

On dispose de 3 classes Qt :

  • QGamepadManager : pour la gestion des manettes branchées
  • QGamepad : le périphérique de jeu connecté au système
  • QGamepadKeyNavigation : pour la prise en charge des événements de clavier déclenchés par la manette de jeu

Qt fournit aussi 5 exemples.

Exemples Qt

#include <QCoreApplication>
#include <QtGamepad/QGamepad>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QList<int> manettes = QGamepadManager::instance()->connectedGamepads();

    if (manettes.isEmpty())
    {
        qDebug() << "Aucune manette détectée !";
        return 0;
    }
    else
    {
        qDebug() << "Nombre de manettes :" << manettes.size();
    }

    for (auto m : manettes)
    {
            QGamepad *manette = new QGamepad(m);
            qDebug() << "Manette :" << m;
            qDebug() << "  device id :   " << manette->deviceId();
            qDebug() << "  nom:        " << manette->name();
            qDebug() << "  connecte ?" << manette->isConnected();
    }

    return a.exec();
}

On obtient avec le joystick MaxFighter F-23 :

...
Nombre de manettes : 1
Manette : 4100
  device id :    4100
  nom:         ""
  connecte ? true
Ctrl-C

Et avec la manette Sony PS3 :

...
Nombre de manettes : 1
Manette : 616
  device id :    616
  nom:         ""
  connecte ? true
Ctrl-C

Code source : qt-manette.zip

La classe QGamepad fournit les signaux liés aux évènements de la manette :

void axisLeftXChanged(double value);
void axisLeftYChanged(double value);
void axisRightXChanged(double value);
void axisRightYChanged(double value);
void buttonAChanged(bool value);
void buttonBChanged(bool value);
void buttonXChanged(bool value);
void buttonYChanged(bool value);
void buttonL1Changed(bool value);
void buttonR1Changed(bool value);
void buttonL2Changed(double value);
void buttonR2Changed(double value);
void buttonSelectChanged(bool value);
void buttonStartChanged(bool value);
void buttonL3Changed(bool value);
void buttonR3Changed(bool value);
void buttonUpChanged(bool value);
void buttonDownChanged(bool value);
void buttonLeftChanged(bool value);
void buttonRightChanged(bool value);
void buttonCenterChanged(bool value);
void buttonGuideChanged(bool value);

On peut donc les connecter à des slots afin de récupérer les informations sur les axes et les boutons.

On obtient maintenant :

...
Nombre de manettes 2
-> Manette 4100
Manette::Manette(QGamepad*, QObject*) QGamepad(0x56240d498600)
Device id 4100
Connecte ? oui
-> Manette 616
Manette::Manette(QGamepad*, QObject*) QGamepad(0x56240d4949c0)
Device id 616
Connecte ? oui
Left X -0.952941 4100
Left X -0.968627 4100
Button R2 0.223529 4100
Button B false 616
Button Guide true 616
0

Code source : qt-manette-test.zip

Prise en charge avec la SDL 2

La SDL (Simple DirectMedia Layer) est une bibliothèque logicielle libre. Son API est utilisée pour créer des applications multimédias comme les jeux vidéo, les démos graphiques, les émulateurs, etc. Sa portabilité sur la plupart des plateformes et sa licence zlib, très permissive, contribuent à son succès.

Elle supporte l’utilisation des joystick : wiki.libsdl.org.

  • Installation :
$ sudo apt-get install libsdl2-dev

Le script sdl2-configfournit permet de connaître les paramètres à utiliser lors de la fabrication d’un programme :

$ sdl2-config --cflags
-I/usr/include/SDL2 -D_REENTRANT

$ sdl2-config --libs
-lSDL2
#include <stdio.h>

#include <SDL.h>
//#include <SDL2/SDL.h>

// Compilation : g++ -I/usr/include/SDL2 -D_REENTRANT joystick-sdl.cpp -lSDL2

int main()
{
    SDL_Joystick *joystick = NULL;
    SDL_Event event;
    int fini = 0;
    
    // SDL avec la gestion des joysticks
    if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) == -1 )
    {
        fprintf(stderr, "Erreur lors de l'initialisation de la SDL !\n");
        return -1;
    }
    
    if (SDL_NumJoysticks() == 1)
    {
        printf("[%s:%s:%d] Il y a %d périphérique de controle connecté\n", __FILE__, __FUNCTION__, __LINE__, SDL_NumJoysticks());
    }
    else if (SDL_NumJoysticks() > 1)
    {
        printf("[%s:%s:%d] Il y a %d périphériques de controle connectés\n", __FILE__, __FUNCTION__, __LINE__, SDL_NumJoysticks());
    }
    else
    {
        printf("[%s:%s:%d] Il n'y a aucun périphérique de controle reconnu\n", __FILE__, __FUNCTION__, __LINE__);
        return 0;
    }

    // Le premier
    joystick = SDL_JoystickOpen(0);
    if (joystick == NULL)
    {
        fprintf(stderr, "Erreur pour ouvrir le premier joystick !\n");
        return -2;
    }
    
    printf("*** Informations ***\n");
    printf("Nom : %s\n", SDL_JoystickName(0));
    printf("Nombre d'axes : %d\n", SDL_JoystickNumAxes(joystick));
    printf("Nombre de hats : %d\n", SDL_JoystickNumHats(joystick));
    printf("Nombre de trackballs : %d\n", SDL_JoystickNumBalls(joystick));
    printf("Nombre de boutons : %d\n", SDL_JoystickNumButtons(joystick));
    printf("********************\n");

    SDL_JoystickEventState(SDL_ENABLE);
    while (!fini)
    {
        //SDL_PollEvent(&event);
        SDL_WaitEvent(&event);
        switch(event.type)
        {
            case SDL_QUIT:
                fini = 1;
                break;
            case SDL_JOYBUTTONDOWN: // state : SDL_PRESSED ou SDL_RELEASED                
                printf("[%s:%s:%d] Bouton %d (%d)\n", __FILE__, __FUNCTION__, __LINE__, event.jbutton.button, event.jbutton.state);
                break;
            case SDL_JOYAXISMOTION:
                printf("[%s:%s:%d] Axe %d %d\n", __FILE__, __FUNCTION__, __LINE__, event.jaxis.axis, event.jaxis.value);
                break;
            case SDL_JOYHATMOTION: // value : SDL_HAT_CENTERED, SDL_HAT_DOWN, ...
                printf("[%s:%s:%d] HAT %d\n", __FILE__, __FUNCTION__, __LINE__, event.jhat.value);
                break;
            case SDL_JOYBALLMOTION:
                printf("[%s:%s:%d] Trackball %d (%d,%d)\n", __FILE__, __FUNCTION__, __LINE__, event.jball.ball, event.jball.xrel, event.jball.yrel);
                break;
        }
    }

    SDL_JoystickClose(joystick);
    
    SDL_Quit();
    
    return 0;
}

Code source : joystick-sdl.cpp.zip

On obtient :

$ g++ -I/usr/include/SDL2 -D_REENTRANT joystick-sdl.cpp -lSDL2

$ ./a.out
[joystick-sdl.cpp:main:28] Il y a 2 périphériques de controle connectés
*** Informations ***
Nom : (null)
Nombre d'axes : 4
Nombre de hats : 1
Nombre de trackballs : 0
Nombre de boutons : 12
********************
[joystick-sdl.cpp:main:62] Bouton 1 (1)
[joystick-sdl.cpp:main:62] Bouton 2 (1)
[joystick-sdl.cpp:main:65] Axe 2 0
[joystick-sdl.cpp:main:65] Axe 2 840
[joystick-sdl.cpp:main:65] Axe 2 1848
[joystick-sdl.cpp:main:65] Axe 2 840
[joystick-sdl.cpp:main:65] Axe 2 0
...

Retour au sommaire