Ok, c’est parti.
Les fichiers à modifier sont dans : « dossier de l’ide arduino »\hardware\teensy\cores\usb_hid.
Les numéros entre crochets dans les balises code sont les numéros de lignes.
• usb.c
Première chose à modifier, le descriptor data du joystick. Un lien qui m’a bien aidé ici et un outil bien pratique là.
Voilà ce que ça donne pour deux gamepads:
[156] static const uint8_t PROGMEM joystick_hid_report_desc[] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
}
Maintenant il faut calculer la taille en octets que fait le rapport:
Étant donné que nous déclarons deux gamepads il faut prendre en compte un octet de report id = 1 octet.
Ensuite, il faut multiplier les deux report_count par leur report_size respectif (exprimés en bits) et les additionner. Ce qui nous fait (161 + 84)/8 = 6 octets.
Notre report fait donc 1 + 6 = 7 octets.
Il faut en effet calculer le report pour un seul gamepad car c’est le report id qui définira à quel gamepad le report s’adresse.
À présent, il va falloir modifier les anciennes déclarations de taille du joystick par la nôtre (12 → 7):
• toujours dans l’usb.c
[364] 7, 0, // wMaxPacketSize
[460] uint8_t joystick_report_data[7] USBSTATE;
[843] for (i=0; i<7; i++) {
Dans la foulée on va modifier l’attribution des valeurs par défaut du report:
[503] joystick_report_data[0] = 0; //report id à changer avant chaque envoi
joystick_report_data[1] = 0; //boutons 1 à 8 non enfoncés
joystick_report_data[2] = 0; //boutons 9 à 16 non enfoncés
joystick_report_data[3] = 0x7F; //axe X à 127 (centré)
joystick_report_data[4] = 0x7F; //axe Y à 127 (centré)
joystick_report_data[5] = 0x7F; //axe Z à 127 (centré)
joystick_report_data[6] = 0x7F; //axe Rx à 127 (centré)
Ne pas oublier de supprimer le reste des attributions (joystick_report_data[7] à joystick_report_data[11] car le tableau a été rétréci).
Voilà qui est terminé pour l’usb.c.
• usb_api.cpp
Rendez-vous ligne 348 pour rétrécir les attributions à UEDATX:
[348] UEDATX = joystick_report_data[0];
UEDATX = joystick_report_data[1];
UEDATX = joystick_report_data[2];
UEDATX = joystick_report_data[3];
UEDATX = joystick_report_data[4];
UEDATX = joystick_report_data[5];
UEDATX = joystick_report_data[6];
• usb_api.h
[62] extern uint8_t joystick_report_data[7];
On va aussi modifier les méthodes de l’objet usb_joystick_class. Gardez juste la méthode button et dupliquez une des méthodes qui s’occupe d’un axe. Nous l’utiliseront pour prendre en charge les autres axes du pad playstation (cf. descriptor data).
[64] class usb_joystick_class
{
public:
inline void num(uint8_t num) {
joystick_report_data[0] = num;
}
inline void button(uint8_t button, bool val) {
button--;
uint8_t mask = (1 << (button & 7));
if (val) {
if (button < 8) { joystick_report_data[1] |= mask; }
else if (button < 16) { joystick_report_data[2] |= mask; }
} else {
mask = ~mask;
if (button < 8) { joystick_report_data[1] &= mask; }
else if (button < 16) { joystick_report_data[2] &= mask; }
}
if (!manual_mode) send_now();
}
inline void X(uint8_t val) {
if (val > 255) val = 255;
joystick_report_data[3] = val;
if (!manual_mode) send_now();
}
inline void Y(uint8_t val) {
if (val > 255) val = 255;
joystick_report_data[4] = val;
if (!manual_mode) send_now();
}
inline void Z(uint8_t val) {
if (val > 255) val = 255;
joystick_report_data[5] = val;
if (!manual_mode) send_now();
}
inline void Rx(uint8_t val) {
if (val > 255) val = 255;
joystick_report_data[6] = val;
if (!manual_mode) send_now();
}
inline void useManualSend(bool mode) {
manual_mode = mode;
}
void send_now(void);
private:
//static uint8_t manual_mode;
uint8_t manual_mode;
};
Une méthode num a été ajoutée, elle va stocker la valeur qu’on lui passera dans le joystick_report_data[0] (cf. le report id).
Deux else if de la méthode button on étés retirés car nos gamepads n’ont que 16 boutons.
Les méthodes des axes ont aussi été modifiées car la bibliothèque PS2X revoie une valeur codée sur un octet (ce qui rend la construction du report_data plus facile).
Pour finir dans usb_private.h
[124] extern uint8_t joystick_report_data[7];
Et le tour est joué!
Il n’y a plus qu’a utiliser l’objet Joystick et ses nouvelles méthodes dans l’IDE Arduino:
Joystick.num(1); //report id a 1 -> on cible le 1er gamepad
Joystick.button(1,1); //le boutton 1 est enfoncé
Joystick.X(0) //stick gauche a gauche
Joystcik.Y(0) //stick gauche en haut
Joystick.Z(255) //stick droit a droite
Joystcik.Rx(255) //stick droit en bas
Voilà, voilà. En espérant que ça serve