Epivoila, blog graphisme developpement referencement

Contrôle du lance missile USB en flash grâce à PERL

- Ecrit par Alexis le Mercredi 8 juillet 2009 | catégorie : Développement web

- Mots clefs : , , , , , ,

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 :-D

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)

Commentaires (4)

Flèche commentaire

[...] à fait un article où il explique comment il a procédé. Et ici, on accède au controle en [...]

- Ecrit par Trinidev » Lance missile USB avec webcam intégrée, le 9 juillet 2009 à 5:13

Flèche commentaire

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.

- Ecrit par clement, le 10 juillet 2009 à 7:43

Flèche commentaire

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 ^^

- Ecrit par neolitec, le 18 août 2009 à 10:43

Flèche commentaire

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 :)

- Ecrit par clement, le 18 août 2009 à 11:37

Postez votre commentaire