Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
materiel:gametrak:start [2025/10/31 21:02]
emoc [Suite]
materiel:gametrak:start [2025/10/31 21:39] (Version actuelle)
emoc [Tentative d'utilisation]
Ligne 13: Ligne 13:
 ===== Tentative d'​utilisation ===== ===== Tentative d'​utilisation =====
  
-En le branchant sur un odi, il est reconnu par ''​lsusb''​+En le branchant sur un ordi, il est reconnu par ''​lsusb''​
   Bus 002 Device 015: ID 14b7:0982 In2Games Ltd. Game-Trak V1.3   Bus 002 Device 015: ID 14b7:0982 In2Games Ltd. Game-Trak V1.3
   Bus 002 Device 014: ID 0f30:001c Jess Technology Co., Ltd PS3 Guitar Controller Dongle   Bus 002 Device 014: ID 0f30:001c Jess Technology Co., Ltd PS3 Guitar Controller Dongle
Ligne 39: Ligne 39:
 Mais impossible de récupérer les données HiD, les tests avec ChucK ou un script python adapté n'ont rien donné. Les formats de communication utilisés sur PS2 pour le USB-HID ne sont pas les mêmes que sur PC, il ne suffit pas d'​avoir un périphérique USB pour pouvoir le brancher sur un PC ou vice versa, triste nouvelle! Mais impossible de récupérer les données HiD, les tests avec ChucK ou un script python adapté n'ont rien donné. Les formats de communication utilisés sur PS2 pour le USB-HID ne sont pas les mêmes que sur PC, il ne suffit pas d'​avoir un périphérique USB pour pouvoir le brancher sur un PC ou vice versa, triste nouvelle!
  
-En me renseignant ​un peu plus sur les gametrak, je note qu'il y a plusieurs versions+**evtest** permet aussi de voir les events liés au périphériques d'​entrée ( https://​manned.org/​evtest ) 
 +  sudo evtest 
 + 
 +==== Évènements bruts HID (hidraw) ==== 
 + 
 +Voici un script python3 pour retrouver les valeurs brutes HID (merci les LLM), à démarrer avec ''​sudo python3 hidraw_reader.py --device /​dev/​hidraw2''​ à adapter en fonction de ce que qu'a relevé dmesg ci-dessus (pour les options en ligne de commande, voir commentaires du script) 
 +<​accordion>​ 
 +<panel title="​hidraw_reader.py (cliquer pour afficher le code)">​ 
 +<code python hidraw_reader.py>​ 
 +#​!/​usr/​bin/​env python3 
 +"""​ 
 +hidraw_reader.py - lire les reports HID bruts depuis /​dev/​hidrawN et afficher hex + timestamp 
 +Usage examples: 
 +  # lister les hidraw disponibles 
 +  python3 hidraw_reader.py --list 
 +  # lire un device précis 
 +  python3 hidraw_reader.py --device /​dev/​hidraw2 
 +  # lire en spécifiant vendor:​product (hex, ex: 046d:​c52b) 
 +  python3 hidraw_reader.py --vidpid 046d:c52b 
 +  # écrire la sortie dans un fichier 
 +  python3 hidraw_reader.py --device /​dev/​hidraw2 --output dump.log 
 + 
 +Fonctions:​ 
 + - détection simple des attributs USB via /sys (idVendor,​idProduct,​manufacturer,​product) 
 + - lecture non-bloquante avec select, affichage hex + ascii + timestamp 
 + - gestion propre des droits (tester en root si permission refusée) 
 +"""​ 
 +import os, sys, time, select, binascii 
 + 
 +def find_hidraw_devices():​ 
 +    """​Retourne liste de dicts: {'​path':'/​dev/​hidraw0','​hid':'​hidraw0','​vid':'​046d',​ '​pid':'​c52b',​ '​manufacturer':​...,​ '​product':​...}"""​ 
 +    res = [] 
 +    devs = sorted([d for d in os.listdir('/​dev'​) if d.startswith('​hidraw'​)]) 
 +    for d in devs: 
 +        path = os.path.join('/​dev',​ d) 
 +        info = {'​path':​ path, '​hid':​ d, '​vid':​ None, '​pid':​ None, '​manufacturer':​ None, '​product':​ None} 
 +        # sys path e.g. /​sys/​class/​hidraw/​hidraw0/​device -> may be a symlink to ../​../​../​.../​usbX/​X-X:​1.X/​... 
 +        try: 
 +            sysnode = os.path.join('/​sys/​class/​hidraw',​ d, '​device'​) 
 +            if os.path.exists(sysnode):​ 
 +                # climb up parents to find idVendor/​idProduct (up to 6 levels) 
 +                p = os.path.realpath(sysnode) 
 +                for _ in range(6): 
 +                    vendor_file = os.path.join(p,​ '​idVendor'​) 
 +                    product_file = os.path.join(p,​ '​idProduct'​) 
 +                    if os.path.exists(vendor_file) and os.path.exists(product_file):​ 
 +                        with open(vendor_file,'​r'​) as f: info['​vid'​] = f.read().strip() 
 +                        with open(product_file,'​r'​) as f: info['​pid'​] = f.read().strip() 
 +                        # optional fields 
 +                        man = os.path.join(p,​ '​manufacturer'​) 
 +                        prod = os.path.join(p,​ '​product'​) 
 +                        if os.path.exists(man):​ 
 +                            try: 
 +                                with open(man,'​r'​) as f: info['​manufacturer'​] = f.read().strip() 
 +                            except: 
 +                                pass 
 +                        if os.path.exists(prod):​ 
 +                            try: 
 +                                with open(prod,'​r'​) as f: info['​product'​] = f.read().strip() 
 +                            except: 
 +                                pass 
 +                        break 
 +                    # climb up 
 +                    parent = os.path.dirname(p) 
 +                    if parent == p: 
 +                        break 
 +                    p = parent 
 +        except Exception as e: 
 +            pass 
 +        res.append(info) 
 +    return res 
 + 
 +def hexdump_line(data,​ base_offset=0):​ 
 +    hexpart = ' '​.join(f"​{b:​02x}"​ for b in data) 
 +    asciipart = ''​.join((chr(b) if 32 <= b < 127 else '​.'​) for b in data) 
 +    return f"​{base_offset:​08x} ​ {hexpart:<​48} ​ |{asciipart}|"​ 
 + 
 +def print_report(ts,​ bts, out): 
 +    # print timestamp and hexdump-like line(s) 
 +    header = f"​[{time.strftime('​%Y-%m-%d %H:​%M:​%S',​ time.localtime(ts))}.{int((ts - int(ts))*1000):​03d}] len={len(bts)}"​ 
 +    print(header,​ file=out) 
 +    # chunk into 16 bytes per line 
 +    for i in range(0, len(bts), 16): 
 +        chunk = bts[i:​i+16] 
 +        print(hexdump_line(chunk,​ i), file=out) 
 +    out.flush() 
 + 
 +def open_nonblocking(path):​ 
 +    import fcntl, os, stat 
 +    fd = os.open(path,​ os.O_RDONLY | os.O_NONBLOCK) 
 +    # make file descriptor a file object for read() 
 +    return os.fdopen(fd,​ '​rb',​ buffering=0) 
 + 
 +def main(): 
 +    import argparse, sys, time 
 +    parser = argparse.ArgumentParser(description="​hidraw reader - affichage des reports HID bruts"​) 
 +    parser.add_argument('​--list',​ action='​store_true',​ help='​Lister les /​dev/​hidraw* détectés'​) 
 +    parser.add_argument('​--device',​ '​-d',​ help='​Chemin vers /​dev/​hidrawN (ex: /​dev/​hidraw2)'​) 
 +    parser.add_argument('​--vidpid',​ help='​Filtrer par vendor:​product hex (ex: 046d:​c52b)'​) 
 +    parser.add_argument('​--interval',​ type=float, default=0.2,​ help='​Timeout select en secondes (default 0.2)'​) 
 +    parser.add_argument('​--output',​ '​-o',​ help='​Chemin fichier pour écrire la sortie (stdout si non fourni)'​) 
 +    args = parser.parse_args() 
 + 
 +    devs = find_hidraw_devices() 
 +    if args.list:​ 
 +        if not devs: 
 +            print("​Aucun /dev/hidraw trouvé."​) 
 +            return 0 
 +        print("​Detected hidraw devices:"​) 
 +        for d in devs: 
 +            print(f"​ {d['​path'​]} ​ vid:​pid={d.get('​vid'​) or '​----'​}:​{d.get('​pid'​) or '​----'​} ​ manufacturer={d.get('​manufacturer'​) or ''​} product={d.get('​product'​) or ''​}"​) 
 +        return 0 
 + 
 +    target = None 
 +    if args.device:​ 
 +        target = args.device 
 +    elif args.vidpid:​ 
 +        v,p = args.vidpid.split(':'​) 
 +        for d in devs: 
 +            if d.get('​vid'​) and d.get('​pid'​) and d['​vid'​].lower() == v.lower() and d['​pid'​].lower() == p.lower():​ 
 +                target = d['​path'​] 
 +                break 
 +        if not target: 
 +            print(f"​Pas de périphérique hidraw correspondant à {args.vidpid}",​ file=sys.stderr) 
 +            return 2 
 +    else: 
 +        # if only one device, choose it 
 +        if len(devs) == 1: 
 +            target = devs[0]['​path'​] 
 +        else: 
 +            print("​Plusieurs périphériques hidraw détectés — précisez --device ou --vidpid, ou utilisez --list pour voir.",​ file=sys.stderr) 
 +            return 3 
 + 
 +    out = sys.stdout 
 +    if args.output:​ 
 +        out = open(args.output,​ '​w',​ buffering=1) 
 + 
 +    print(f"​Opening {target} (non-blocking) ...", file=sys.stderr) 
 +    try: 
 +        f = open_nonblocking(target) 
 +    except PermissionError:​ 
 +        print("​Permission refusée: lancez en root ou ajustez udev pour accéder à /​dev/​hidraw*",​ file=sys.stderr) 
 +        return 4 
 +    except FileNotFoundError:​ 
 +        print("​Fichier non trouvé:",​ target, file=sys.stderr) 
 +        return 5 
 + 
 +    print("​Entering read loop. Press Ctrl-C to stop.",​ file=sys.stderr) 
 + 
 +    try: 
 +        while True: 
 +            r, _, _ = select.select([f],​ [], [], args.interval) 
 +            if not r: 
 +                # timeout; continue to allow Ctrl-C responsiveness 
 +                continue 
 +            try: 
 +                data = f.read(64) ​ # typical hid report length; if returns b''​ skip 
 +            except BlockingIOError:​ 
 +                continue 
 +            if not data: 
 +                # no data read; continue 
 +                continue 
 +            ts = time.time() 
 +            print_report(ts,​ data, out) 
 +    except KeyboardInterrupt:​ 
 +        print("​\nStopped by user.",​ file=sys.stderr) 
 +        return 0 
 + 
 +if __name__ == '​__main__':​ 
 +    sys.exit(main()) 
 + 
 +</​code>​ 
 +</​panel>​ 
 +</​accordion>​ 
 + 
 + 
 +==== Renseignons-nous ==== 
 + 
 +En recherchant ​un peu plus sur les gametrak, je note qu'il y a plusieurs versions
   - Version 1 : autre facteur de forme, facile à reconnaître   - Version 1 : autre facteur de forme, facile à reconnaître
   - Version 2 Rev 1.x : USB-HID compatible PS2 uniquement (*)   - Version 2 Rev 1.x : USB-HID compatible PS2 uniquement (*)
Ligne 46: Ligne 224:
 (C'est probablement une seule soudure qui fait la différence entre les version V2 Rev2 PS2 et PC/XBox) (C'est probablement une seule soudure qui fait la différence entre les version V2 Rev2 PS2 et PC/XBox)
  
-(*) La version 2 Rev 1 peut être réutilisée en refabriquant l'​électronique à partir dune carte arduino ou teensy, mais ça prendrait un peu de patience et aurait aussi un coût... +(*) La version 2 Rev 1 peut être réutilisée en refabriquant l'​électronique à partir dune carte arduino ou teensy, mais ça nécessiterait pas mal de patience et aurait aussi un coût...
  
 +==== Hardware ====
  
-Avant de découvrir tout ça, je l'ai démonté pour vérifier que tout ça se passe bien au niveau des capteurs, à l'​intérieur on trouve 2 doubles potentiometres pour XY, type joystick, assez classiques et 2 potentiometres qui permettent qui mesure ​l'​élongation en Z avec un système de poulies. C'est quand même bien ingénieux tout ça!+Avant de découvrir tout ça, je l'ai démonté pour vérifier que tout ça se passe bien au niveau des capteurs ​(et lire la version du pcb), à l'​intérieur on trouve 2 doubles potentiometres pour XY, type joystick, assez classiques et 2 potentiometres qui mesurent ​l'​élongation en Z avec un système de poulies. C'est quand même bien ingénieux tout ça! \\
 En testant les potentiomètres tout fonctionne d'un point de vue mécanique et électrique En testant les potentiomètres tout fonctionne d'un point de vue mécanique et électrique
  
  • materiel/gametrak/start.1761940932.txt.gz
  • Dernière modification: 2025/10/31 21:02
  • par emoc