Bidouillage d'un ventilateur USB avec affichage de message (1/2) [fr]
Historique
Remarque: cet historique est un peu long, ne pas le lire n’affectera pas la compréhension de ce qui a été réalisé. Néanmoins, j’ai pris la peine de l’écrire, alors lisez-le si vous voulez me faire plaisir. :)
Il y a quelque mois de cela, lors d’un événement “Pitch me up”, quelqu’un a présenté une sorte de cadre photo numérique, mais basé sur des bandes de LEDs RGB de forte luminosité.
M’intéressant à intervalles plus ou moins régulier au sujet, j’ai discuté avec le concepteur dudit cadre. Le rendu visuel est excellent, surtout avec la disponibilité de bandes de LEDs de densité de plus en plus élevée, mais voilà, il y a un problème de coût non négligeable.
Je me suis alors souvenu d’une ancienne console, nommée Adventure Vision, qui utilise une seule bande de 40 LEDs, couplée avec un miroir rotatif qui permet un affichage de 150x40 en utilisant la persistance rétinienne.
Entex Adventure Vision, à ranger avec la MB Vectrex et le Nintendo Virtual Boy dans la série “technologies d’affichage bizarroïdes”.
Chemin faisant (dans mon esprit), j’en viens à l’idée d’utiliser le même principe pour réaliser un affichage circulaire cette fois, en faisant tourner une unique bande de LEDs. L’idée de la Twatch, ou Twitter Watch n’était pas loin: mélanger un affichage d’une horloge “classique”, avec des messages provenant d’une source dynamique (un fil twitter me semblant bien adapté).
Une première version a été entreprise. Les parties électronique et logicielle ne présentent pas de difficulté en ce qui me concerne, en revanche, la partie mécanique n’est pas mon fort, et je n’ai pas trouvé de solution satisfaisante, donc j’ai mis ce projet au placard, en attendant d’être mieux inspiré.
Inutile, donc indispensable
Par un heureux hasard, quelqu’un me parle de cet objet, qui réalise à priori tout ce dont j’ai besoin (pour une première version), et ce, à un prix dérisoire.
A moins de 10 euros, un nerdgasm pas cher!
Quelques infos sur l’objet:
- La bande de LEDs est monochrome (bleue) et est consitutée de 11 LEDs.
- On peut configurer 8 messages de 26 caractères.
- Chaque message possède les caractérisitques suivantes: effet d’apparition, rotation (ou non) du message, effect de disparition.
- Si on veut afficher autre chose que du texte, c’est possible à l’aide d’un éditeur graphique.
- La programmation de la configuration se fait via USB. Aucun driver n’est requis.
Les points les plus ennuyeux:
- Il n’y a pas de reconfiguration dynamique. On est soit en mode “configuration”, soit en mode “affichage”.
- Le logiciel de configuration est closed-source, et n’est disponible que sous Windows.
Ce dernier point n’est pas cool du tout. Allez hop, on attaque le reverse-engineering.
Etude du protocole de chargement de la configuration
Plutôt que de partir sur l’analyse du programme lui-même (avec un désassembleur et tout l’attirail autour), je me dis que le protocole de chargement ne doit pas être très compliqué.
Au niveau de l’OS, ce ventilateur est vu comme un périphérique USB HID (Human Interface Device, tels un clavier ou une souris). Ceci est généralement un bon choix, si la vitesse importe peu, et surtout c’est reconnu “out-of-the-box” par tous les systèmes, sans driver additionnel.
Je choisis donc d’analyser ce qui se passe au niveau USB.
Je me crée vite fait une VM Windows dans VirtualBox.
Je trouve l’outil SnoopyPro, que j’installe dans la VM, et c’est parti.
Comparaison du comportement du logiciel original et de sa réimplémentation…
Le protocole est (sans surprise) assez simple. Chaque message à afficher commence par l’envoi de 8 octets de données avec le format suivant:
a0 10 xy zn 55 00 00 00
|| ||
|| |+--- Numéro de message (0 à 7)
|| +---- Rotation: 0=Aucune, 6=Counter-clockwise, c=Clockwise
|+------ Numéro de l'effet de disparition (0 à 5)
+------- Numéro de l'effet d'apparition (0 à 5)
La réponse à cette requète contient l’echo des données envoyées, au premier octet près, qui est $a1 au lieu de $a0.
Ensuite, l’état des LEDs est envoyé sous forme de bitmap, colonne par colonne, en inverse, en packant les états des 11 LEDs dans 16 bits. Oui, ce que je viens d’écrire est incompréhensible, alors prenons un petit exemple:
/---------------------\ /---------------------\ /---------------------\
ff fd ff fd ff fd ff fd ff fd ff ff ff 81 ff 6f ff 6f ff 6f ff 81 ff ff
\ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ / \ ~ /
\ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
0 . . . . . . . . . . . .
0 . . . . . . . . . . . .
0 . . . . . . . . . . . .
0 . . . . . . . . . . . .
1 . . . . . . . . . . . .
1 . . . . . . . . . . . .
1 . . . . . . . . . . . .
1 . . . . . . . . . . . .
2 . . . . . . . # # # . .
2 . . . . . . # . . . # .
2 . . . . . . # . . . # .
2 . . . . . . # # # # # .
3 . . . . . . # . . . # .
3 . . . . . . # . . . # .
3 # # # # # . # . . . # .
3 . . . . . . . . . . . .
La réponse à ce type de requête est l’echo de celle-ci, sans modification.
Un peu de calcul, maintenant:
- Pour 8 messages affichés, il y a 1280 trames échangées.
- Par message, cela représente 1280 / 8 = 160 trames.
- Chaque échange fait intervenir 4 trames, on a donc 160 / 4 = 40 requêtes.
- La première requète contient les caractéristiques du message, il en reste donc 39 pour constituer le bitmap.
- Chaque message comprend 26 caractères, et il faut 3 requêtes pour en afficher 2 (voir ci-dessus), donc on a 26 / 2 * 3 = 39 requêtes pour transférer le bitmap complet.
Le compte est bon!
A noter que si on transfère moins de 8 messages, alors la première requête prend la forme suivante:
a0 10 ff 0n ff ff ff ff
|
+--- Numéro de message (0 à 7)
La réponse à cette requête est l’echo de celle-ci, sans modification du $a0 en $a1. Elle est suivie de données de bitmap “à blanc” (que des $ff).
A suivre
L’analyse du protocole a pris assez peu de temps. Reste maintenant à en proposer une implémentation libre, ce qui veut dire développer autour du standard USB. Or le(s) standard(s) USB ne sont pas simples, dû à un historique que je qualifierai de… torturé.
Cette partie sera abordée dans un post dédié.
blog comments powered by Disqus