Utilisation d'une Wiimote comme souris
Tutoriel concernant l'utilisation d'une Wiimote sous Ubuntu.
Vous pourrez alors utiliser votre Wiimote en tant que souris, sans aucun effort, ou presque.
Pré-requis
- Posséder un émetteur/récepteur Bluetooth. La liste du matériel supporté par la wiimote est ici ;
- Avoir une Wiimote… ;
- Allumer une sensorbar (barre infrarouge) ou une bougie voire un projecteur infrarouge (facilement trouvable dans le commerce et pas cher).
Installation
Installez les paquets lswm, wmgui, wminput ou exécutez la commande ci-dessous.
sudo apt-get install lswm wmgui wminput
Petit script qui automatise l'utilisation
Depuis que j'ai découvert ce tutoriel, je me suis lancé dans la fabrication d'un petit script permettant l'exécution en mode graphique.
Il nécessite aussi des droits d'administration. Il faut donc le lancer avec gksudo.
Copiez ce code dans un fichier texte et rendez-le exécutable (Clic droit → Propriétés → Permissions → Exécution : cochez la case autorisant).
#!/bin/bash #Script réalisé par KicheTof pour les utilisateurs de WiiMote. #Script libre de toute modification sans aucune demande nécessaire :) #Vive le libre :) function quit { if [ $? != "0" ]; then exit 1 fi [ $? -ne "0" ] && exit 2 } device=$(hcitool scan | tail -n +2 | while read line do echo -n "$line" | sed -r "s/\s*([0-9A-Fa-f:]+)\s*(.*)/\1\n\2\n/" done | zenity --list \ --title "Utilisation de la WiiMote comme souris : 3 méthodes !" \ --text "Maintenez la touche 1 et 2 en même temps pour activer le mode détection.\nChoisissez la WiiMote dans la liste (Nintendo RVL-CNT)" \ --column "id" --column "appareil bluetooth") quit; while [ ! "$CHOIX_ACTION" ] do CHOIX_ACTION=$(zenity --list --width "600" --height "200" \ --title "Choisissez quelle méthode pour utiliser la WiiMote" \ --text "Pilotage par Accéléromètre, par Infrarouge, ou via le Nunchuk" \ --radiolist \ --column "Choix" --column "Pilotage" --column "Description" \ True Accéléromètre "Utilisation de la position de la WiiMote" \ False Infrarouge "Utilisation de l'infrarouge à l'aide d'une bougie, par exemple" \ False Nunchuk "Utilisation du nunchuk pour piloter la souris") quit; if [ $CHOIX_ACTION == "Accéléromètre" ]; then action="acc_ptr"; elif [ $CHOIX_ACTION == "Infrarouge" ]; then action="ir_ptr"; elif [ $CHOIX_ACTION == "Nunchuk" ]; then action="nunchuk_acc_ptr"; fi done zenity --info --title "Attention" --text "Si les led's ne clignotent plus, réappuyez sur 1 et 2 !\n\nPour quitter le script, pressez 3 secondes le bouton \"power\" de la WiiMote ! :)"; wminput -c $action $device;
0
Vérifier que tout fonctionne avec Wmgui
Nous allons maintenant vérifier que les capteurs de la Wiimote sont bien gérés par l'ordinateur.
Lancez Wmgui grâce au lanceur se trouvant dans Application → Accessoires.
wmgui
sudo ln -s /usr/local/lib/libcwiid.so.1.0 /usr/lib/libcwiid.so.1
Allez dans File → Connect pour vous connecter à la Wiimote.
Cliquez alors sur Valider.
On peut afficher l'état courant de la Wiimote connectée :
- Settings → Acc data permet d'afficher les données concernant l'accéléromètre ;
- Settings → IR data permet d'afficher les données concernant l'infrarouge.
L'accéléromètre fonctionne plutôt bien. Pour vérifier l'infrarouge, vous devez brancher une barre de détection (sensorbar, en anglais) ou utiliser une simple bougie (ça fonctionne chez moi !). L'idée est d'avoir une source ponctuelle d'infrarouge pour que la Wiimote se repère.
WIIMOTE_BDADDR=uu:vv:ww:xx:yy:zz export WIIMOTE_BDADDR
Pour éviter de saisir ces commandes à chaque fois que vous lancez votre session, il suffit de placer ces lignes dans votre fichier ~/.bashrc.
Faire fonctionner la Wiimote grâce à wminput
Tout d'abord, on va chercher l'adresse Mac de notre Wiimote. Pour l'obtenir, tapez la commande ci-dessous dans un terminal.
lswm
Ce petit programme va vous demander de mettre votre Wiimote en mode visible (appuyez sur 1 et 2 en même temps) et vous renvoie l'adresse Mac de la Wiimote.
sudo hidd --search
L'adresse est de la forme « xx:xx:xx:xx:xx:xx ».
Dans certains cas, il est utile de charger un module pour faire fonctionner « wminput ». Un « lsmod » vous le dira. Dans le doute, tapez la commande ci-dessous.
sudo modprobe uinput
Et là, c'est presque gagné. Il existe (pour l'instant) trois façons de lancer « wminput ».
Mode accéléromètre
sudo wminput -c acc_ptr xx:xx:xx:xx:xx:xx
Cette commande permet d'utiliser uniquement l'accéléromètre pour le contrôle de la souris. Il faut la pencher en avant & en arrière et la tourner sur elle-même.
Mode infrarouge
sudo wminput -c ir_ptr xx:xx:xx:xx:xx:xx
Cette commande permet d'utiliser le pointeur infrarouge de la Wiimote. Il faut, au préalable, avoir une sensorbar sous tension ou simplement une bougie éclairant vers la Wiimote. Une vieille télécommande infrarouge et un élastique fonctionnent également. Sans doute la plus utile. Si ça ne fonctionne pas tout de suite, il faut redémarrer la machine.
Mode nunchuk
(Fonctionne sur la version 0.6.00.)
sudo wminput -c nunchuk_acc_ptr xx:xx:xx:xx:xx:xx
Cette commande permet d'utiliser l'accéléromètre du nunchuk pour le contrôle de la souris. L'utilisation est similaire au mode accéléromètre.
sudo hidd --kill xx:xx:xx:xx:xx:xx
/etc/cwiid/wminput
Il est même possible de modifier et de créer ses propres fichiers de configuration.
Pour aller plus loin
Configurations personnalisées / Mapping
Il est possible de personnaliser les actions de la Wiimote en assignant d'autres touches à ses boutons.
Si on regarde le fichier /etc/cwiid/wminput/ir_ptr, on observe que celui-ci inclut le fichier buttons qui régit les touches et assigne une manière de gérer les axes de la souris.
On peut commencer sur la base de acc_ptr (ou ir_ptr si vous préférez l'infrarouge) et ajouter dedans les boutons que l'on veut à l'aide de la commande ci-dessous.
sudo cp /etc/cwiid/wminput/acc_ptr /etc/cwiid/wminput/ma_config
Si vous préférez l'infrarouge, vous pouvez utiliser la commande suivante.
sudo cp /etc/cwiid/wminput/ir_ptr /etc/cwiid/wminput/ma_config
On peut ensuite éditer ce fichier (Pensez à retirer la ligne « include buttons » pour éviter les conflits !).
Voici un exemple de fichier personnalisé.
Plugin.acc.X = REL_X Plugin.acc.Y = -REL_Y # Je trouve ça plus naturel en négatif Plugin.led.Battery = 1 # Pour afficher l'état de la batterie quand on appuie simultanément sur A et B Wiimote.A = BTN_LEFT # Clic gauche Wiimote.B = BTN_RIGHT # Clic droit Wiimote.Up = KEY_UP # Touche Haut △ Wiimote.Down = KEY_DOWN # Touche Bas ▽ Wiimote.Left = KEY_LEFT # Touche Gauche ◁ Wiimote.Right = KEY_RIGHT # Touche Droite ▷ Wiimote.Home = KEY_HOMEPAGE # Touche multimédia Home (Dossier personnel) Wiimote.1 = KEY_PLAYPAUSE # Touche multimédia Jouer/Pause ▸ Wiimote.2 = KEY_NEXTSONG # Touche multimédia Titre suivant Wiimote.Plus = KEY_VOLUMEUP # Touche multimédia Volume + Wiimote.Minus = KEY_VOLUMEDOWN # Touche multimédia Volume -
Vous pouvez ensuite le tester avec la commande ci-dessous.
sudo wminput -c ma_config XX:XX:XX:XX:XX:XX
La liste des boutons de la Wiimote est disponible à l'adresse suivante : http://abstrakraft.org/cwiid/browser/doc/wminput.list.
La liste des touches gérées est disponible à l'adresse suivante : http://abstrakraft.org/cwiid/browser/wminput/action_enum.txt.
Tableau numérique interactif (TNI / whiteboard / TNWii)
L'origine du TNWii : http://www.cs.cmu.edu/~johnny/projects/wii/.
Les pilotes pour faire votre TNWii (sous Hardy, Intrepid et suivants…) : http://code.google.com/p/linux-whiteboard/downloads/list.
Ou les sources par le svn : http://linux-whiteboard.googlecode.com/svn/trunk/.
Une autre version (qui devrait mieux fonctionner) existe également (GTKWhiteboard) : http://forum.ubuntu-fr.org/viewtopic.php?id=208957&p=3 (ce lien mêne au forum qui présente également d'autres ressources sur le TNWii).
Un tutoriel en français pour utiliser le tableau interactif Wiimote sous linux : http://trucsinformatiques.free.fr/articles.php?lng=fr&pg=32 (obsolète, les paquets cités ci-dessus sont plus récents).
Démon et auto-connexion
Il est lassant d'avoir à saisir toutes ces commandes avant de pouvoir profiter de sa wiimote. On peut lancer un démon chargé de se (re-)connecter automatiquement à votre Wiimote quand elle est détectée.
- N'oubliez pas de personnaliser le fichier de configuration.
- Le propriétaire du démon doit disposer des permissions en lecture/écriture sur
/dev/uinput
(regardez du côté de udev). - Copiez ensuite le script ci-dessous dans
/etc/init.d/wminput
.
#! /bin/sh ### BEGIN INIT INFO # Provides: wiimote # Required-Start: $local_fs $syslog $remote_fs bluetooth udev # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Wminput for wiimote initscript # Description: Wiimote for wiimote initscript : should be placed in /etc/init.d. ### END INIT INFO # Author: LvR # Do NOT "set -e" # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="wminput initscript" NAME=wminput DAEMON=/usr/bin/$NAME DAEMON_ARGS="-d" PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Be sure that uinput module is loaded modprobe uinput # Add specific daemon args [ -n "$WMINPUTCONF" ] && DAEMON_ARGS="$DAEMON_ARGS -c $WMINPUTCONF" [ -n "$WIIMOTEADDR" ] && DAEMON_ARGS="$DAEMON_ARGS $WIIMOTEADDR" [ -n "$EXTRAOPTS" ] && DAEMON_ARGS="$DAEMON_ARGS $EXTRAOPTS" # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } # # Function that sends a SIGHUP to the daemon/service # do_reload() { # # If the daemon can reload its configuration without # restarting (for example, when it is sent a SIGHUP), # then implement that here. # start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME return 0 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; #reload|force-reload) # # If do_reload() is not implemented then leave this commented out # and leave 'force-reload' as an alias for 'restart'. # #log_daemon_msg "Reloading $DESC" "$NAME" #do_reload #log_end_msg $? #;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 exit 3 ;; esac exit 0
Le fichier de configuration /etc/default/wminput : Dans cet exemple il faut penser à remplacer « xbmc » par le fichier de configuration des boutons de son choix (voir 5.1 Configurations personnalisées / Mapping). Il faut aussi remplacer 00:21:BD:25:51:C6 par l'adresse Mac de sa Wiimote (voir 4 Faire fonctionner la Wiimote grâce à wminput).
# This file is sourced by /etc/init.d/wminput # # When wminput is started using the init script, the # -d option is always used. # # Each setting is marked either "required" or "optional"; # leaving any required setting unconfigured will cause # the service to not start. # [optional] wiimote mac address : WIIMOTEADDR=00:21:BD:25:51:C6 # [optional] wminput configuration to use : WMINPUTCONF=xbmc # [optional] extra command line options, if any: EXTRAOPTS=
Rendez le service activable avec la commande ci-dessous.
sudo chmod u+x /etc/init.d/wminput
Pour ajouter le service au démarrage, il faut utiliser la commande suivante.
sudo update-rc.d -f wminput defaults
Pour lancer(/stopper/relancer) le démon, il faut utiliser la commande ci-dessous.
sudo service wminput start
Vous pouvez à présent connecter votre WiiMote simplement en appuyant sur 1+2, l'éteindre (en maintenant le bouton POWER) et la ré-allumer sans avoir à lancer quoique ce soit.
Résolutions de problèmes
Curseur enfermé dans une boîte ou souris inactive
Si votre curseur semble « enfermé dans une boîte invisible » ou « reste bloqué » en mode infrarouge, c'est que la caméra de la Wiimote a une résolution de 1024x768 et que les réglages initiaux indiquent à la Wiimote d'utiliser sa résolution native. Pour régler ce problème il faut éditer le fichier /etc/cwiid/wminput/ir_ptr
et remplacer
Plugin.ir_ptr.X = ~ABS_X Plugin.ir_ptr.Y = ~ABS_Y
par
Plugin.ir_ptr.X = ABS_X Plugin.ir_ptr.Y = ABS_Y
Problème de droits avec udev
Pour piloter correctement la wiimote, il faut les droits, en lecture et en écriture, sur le périphérique /dev/uinput
. Étrangement, udev refuse d'appliquer le CHMOD. Pour y remédier, on va demander à udev d'appliquer le CHMOD de la règle le plus tard possible en remplaçant le =
par un :=
.
Voici un exemple à placer dans /etc/udev/rules.d/
. Il faut créer un nouveau fichier. Donc, pensez à la commande suivante, par exemple.
gksudo gedit /etc/udev/rules.d/wiimote
KERNEL=="uinput", CHMOD:="0666"
Problème avec les applications en plein écran
Il est possible que la Wiimote, utilisée avec l'infrarouge, fonctionne mal avec les applications en plein écran. Pour cela, il faut éditer le fichier /etc/environment
via la commande suivante.
sudo nano /etc/environment
Ajoutez-y en-dessous de la grande ligne le petit code suivant.
SDL_VIDEO_X11_DGAMOUSE=0
Le problème est apparemment dû à l'utilisation de la librairie libSDL. Néanmoins, si le bogue se produit dans un environnement spécifique (comme XBMC en standalone), il est préférable d'ajouter ceci au script correspondant à l'environnement.