Ca faisait déjà quelques temps que j’avais envie de connecter le Lance Missile USB de nico à flash. Mais la galère! Après beaucoup de temps passé a tester avec plusieurs langages (interfaces en PHP, en python), j’ai trouvé le moyen de recréer un driver sous PERL. Je ne connaissais pas du tout ce langage quand je m’y suis mis, alors chaud… C’est très très spécial, mais ça à l’air super puissant. Après de bonnes heures de tatonnage et de galère, après beaucoup de code et d’exemples récupérés sur le net, j’ai réussi à faire une passerelle USB / Socket en perl
#!C:\\perl\ require Device::USB; require IO::Socket; require IO::Select; print "Lancement de l'application rocket-server\n"; # Les variables pour cibler le périphérique usb our $vendorID = 0x1130; our $productID = 0x0202; # Le périphérique our $dev; # La première séquence our $initA = join ('', map { chr $_ } (85, 83, 66, 67, 0, 0, 4, 0)); # La seconde our $initB = join ('', map { chr $_ } (85, 83, 66, 67, 0, 64, 2, 0)); # La séquence de commande principale our $commandFill = join ('', map { chr $_ } ( 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); # La liste des commandes $commandList->{stop} = join('', map { chr $_ } ( 0, 0, 0, 0, 0, 0)).$commandFill; $commandList->{left} = join('', map { chr $_ } ( 0, 1, 0, 0, 0, 0)).$commandFill; $commandList->{right} = join('', map { chr $_ } ( 0, 0, 1, 0, 0, 0)).$commandFill; $commandList->{up} = join('', map { chr $_ } ( 0, 0, 0, 1, 0, 0)).$commandFill; $commandList->{down} = join('', map { chr $_ } ( 0, 0, 0, 0, 1, 0)).$commandFill; $commandList->{leftup} = join('', map { chr $_ } ( 0, 1, 0, 1, 0, 0)).$commandFill; $commandList->{rightup} = join('', map { chr $_ } ( 0, 0, 1, 1, 0, 0)).$commandFill; $commandList->{leftdown} = join('', map { chr $_ } ( 0, 1, 0, 0, 1, 0)).$commandFill; $commandList->{rightdown} = join('', map { chr $_ } ( 0, 0, 1, 0, 1, 0)).$commandFill; $commandList->{fire} = join('', map { chr $_ } ( 0, 0, 0, 0, 0, 1)).$commandFill; # La méthode du périphérique USB sub _initUSB { # Séquence de démarrage print "Recherche du peripherique...\n"; # Créer le contrôleur USB my $usb = Device::USB->new(); # Recherche le périphérique $dev = $usb->find_device($vendorID, $productID); # Vérifier si le périphérique à été trouvé if (defined $dev) { # Initialiser le périphérique $dev->open(); $dev->detach_kernel_driver_np(0); $dev->set_configuration(1); $dev->claim_interface(0); $dev->claim_interface(1); # C'est ok return 1; } else { # C'est pas ok return 0; } } # Envoyer des données sub _sendUSB { # Récupérer la commande my $commande = $_[0]; # Envoie de la commande print "Envoie de la commande '".$commande."'\n"; # Vérifier que cette commande existe bien if (defined $commandList->{$commande}) { # Envoyer la commande $dev->control_msg(0x21, 9, 0x2, 0x01, $initA, 8, 1000); $dev->control_msg(0x21, 9, 0x2, 0x01, $initB, 8, 1000); $dev->control_msg(0x21, 9, 0x2, 0x0, $commandList->{$commande}, 64, 5000); # La commande a été envoyée print "Commande ok\n"; return 1; } else { # On dit que ça marche pas print "Erreur: Commande introuvable.\n"; return 0; } } # Initialisation du socket sub _initSocket { print "En attente de connection sur le port 1337\n"; # Configurer le socket $/ = "\0"; # Ouverture du socket my $server = IO::Socket::INET->new(LocalAddr => "localhost", LocalPort => 1337, Reuse => 1, Listen => 5, Proto => 'TCP') or return 0; my $listener = new IO::Select($server); # Ecouter les nouvelles connections while(my @data = $listener->can_read) { # Décortiquer les données foreach (@data) { # Nouvelle connection if ($_ == $server) { # Accepter la connection my $client = $server->accept; # Ajouter cet utilisateur $listener->add($client); # Signaler print "Connection ok\n"; } else { # Récéption d'un message my $sysreadReturn = sysread($_, $infoRead, 2048); # Le message est vide if($sysreadReturn == 0) { # Message de déconnection $syswriteToClient = syswrite($_, '', 2048); # Déconnecter le client if($syswriteToClient == undef) { # L'enlever de la liste $listener -> remove($_); # Deconnection print "Deconnection...\n"; # Péter la boucle return 1; } } else { # Tronquer la commande (bug de l'espace de fin) $command = substr($infoRead, 0, length($infoRead) - 1); # Exécuter la commande print "Receotion de la commande: [".$command."]\n"; # Envoyer la commande au pilote USB _sendUSB($command); } } } } # Fin return 1; } # Initialiser if (_initUSB()) { # Le périphérique à été trouvé, youpi print "Peripherique ok (".$dev->idVendor.", ".$dev->idProduct.")\n"; # Initialiser le socket if (!_initSocket()) { print "Erreur: Impossible de creer le socket!\n"; } } else { # Le périphérique n'a pas été trouvé print "Erreur: Le peripherique n'a pas ete trouve\n"; } # Fermeture du programme print "Fermeture du programme.\n";
Ce programme fonctionne sous ActivePerl 5.10.0, avec l’extension Device-USB
Le fonctionnement n’est pas très compliqué.
Le programme PERL se lance, il récupère le port USB sur lequel le lance missile est lancé, une fois trouvé, il s’y connecte. Après, j’ouvre un socket en local, qui permet de recevoir des commandes (left right up down fire, et les diagonales). Le plus dur fût de trouver les codes hexa à balancer au lance missile, heureusement j’ai trouvé ces séquences sur le net (encore un blog de japs fou furieux, merci la traduction google), mais pas dans le bon langage, aïe aïe aïe… Après traduction en PERL, j’écoute sur le socket et je retransmet la commande au port USB
Voilà, le plus dur était fait, plus qu’a connecter ça à flash. J’ai décidé de créer encore une passerelle, en flex/air, qui permet de lancer le programme PERL, de s’y connecter en socket, et d’envoyer les commandes grâce à des boutons. Après, le plus fun à été de scotcher une webcam comme un gros bourrin sur le lance missile, et d’interfacer le tout sur un FMS! Encore plus fun, j’ai connecté la passerelle à une manette Wii grâce à WiiFlash, pour diriger le tout en bluetooth ^^
Voilà ce que ça donne, vous pouvez vous connecter de partout, sur le lance-missile du boulot (c’est en ligne qu’aux heures où je taff) :
Lance Missile USB de La Haute Société
Il manque plein d’options, comme un tchat, un système de ticket pour que chacun puisse contrôler à son tour (là c’est l’anarchie), un multi-angle, et d’autres conneries
Enjoy!
PS: Je cherche à compiler cette application PERL en .exe (je sais que c’est pas logique de compiler du perl, mais c’est pour pouvoir le lancer silencieusement depuis air)
Moi je pense que t’es complètement malade et que c’est vraiment fun !
Beau boulot et merci pour l’article, ca me donne un peu des frissons les codes hexa.
Je viens voir le lance missile USB de temps en temps mais… je ne l’ai vu allumé qu’une fois
En tout cas superbe travail ! Pour un truc complètement inutile ^^
Erf c’est pas de chance, moi je le vois souvent allumé et j’ai bien abusé des roquettes
Essayes de demander à zouloux sur twitter de l’allumer
[...] à fait un article où il explique comment il a procédé. Et ici, on accède au controle en [...]