Hack and / - Wiimote Control
August 1st, 2008 by Kyle Rankin in
If you think about it, there are almost as many ways to interface with your computer as there are Debian-based distributions—and that's a lot. Besides the trusty keyboard and optical mouse, there are trackpoint mice, touchpads, touchscreens, twiddlers, joysticks, presentation remotes and even devices that measure your brain waves. Although I mostly stick with my tried-and-true keyboard and trackpoint mouse (fingers on home row, thank you), when I started hearing about all the interesting things people were doing with the Wiimote (the main controller from the Nintendo Wii), I knew I had to give it a try.
Now traditionally, connecting a brand-new device to a Linux machine was an investment in Internet research, kernel module hacking, prayer and obscure programming skills I haven't used since college. I figured the mere fact that this was a Bluetooth device meant I was going to have to spend some quality time with hcidump. To my surprise, all the hard work already had been done for me, and I could connect and use a Wiimote on my laptop with only a few basic steps.
First, your kernel needs the uinput module available and loaded. This module is available in modern kernels, and my Ubuntu Gutsy install already had it. If you want to be able to connect to the Wiimote as a regular user, however, you need to add a new udev rule to extend permissions to the uinput device. I created a file called /etc/udev/rules.d/95-uinput.rules that contained the following:
KERNEL=="uinput", GROUP="plugdev"
Then, I made sure my user was a member of the plugdev group. If your system doesn't have a plugdev group, you could choose or create another group to use for this device. Next, run /etc/init.d/udev reload to make sure your changes are seen. Finally, I ran modprobe uinput to make sure the module was loaded, and I also added uinput to /etc/modules to make sure it was loaded at boot.
The next step is to install the wminput software. For me, this was simple, as wminput is packaged for my distribution; otherwise, you can download the source from the official site (www.cwiid.org). Then, make sure the Bluetooth device in your computer is enabled. For my laptop, I had to flip a switch on the side, but if you have an external USB Bluetooth adapter, for instance, now is a good time to plug it in. Finally, run wminput in a console and follow the directions:
greenfly@minimus:~$ wminput Put Wiimote in discoverable mode now (press 1+2)... Ready.
When you press buttons 1 and 2 on your Wiimote, it goes into discoverable mode, and the blue LEDs along the bottom start blinking. Sometimes you might not start discoverable mode fast enough, or wminput won't detect it, but as long as the LEDs on the Wiimote are blinking, it is still in that mode. So if wminput times out, just run the program again.
If you continually can't connect, you probably should double-check that your Bluetooth device is working. To do this, press buttons 1 and 2 on the Wiimote and then use hcitool to scan for the Wiimote. A successful scan will look like the following:
greenfly@minimus:~$ hcitool scan
Scanning ...
00:1B:7A:3E:8C:54 Nintendo RVL-CNT-01
After wminput connects, you also can look in /var/log/dmesg for confirmation that the Wiimote is connected:
[ 1226.247203] usb 3-2: new full speed USB device using ↪uhci_hcd and address 13 [ 1226.288768] usb 3-2: configuration #1 chosen ↪from 1 choice [ 1227.922403] input: Nintendo Wiimote as ↪/devices/virtual/input/input21
Once the Wiimote is connected, the default bindings use it as a mouse. The accelerometers in the Wiimote are used to move the mouse pointer, so if you point the Wiimote down or up, the mouse will move down or up, respectively, and if you roll the Wiimote to the left or right, the mouse will move left or right, respectively. If you look at /etc/cwiid/wminput/buttons, you can see the default mappings:
Wiimote.A = BTN_LEFT Wiimote.B = BTN_RIGHT Wiimote.Up = KEY_UP Wiimote.Down = KEY_DOWN Wiimote.Left = KEY_LEFT Wiimote.Right = KEY_RIGHT Wiimote.Minus = KEY_BACK Wiimote.Plus = KEY_FORWARD Wiimote.Home = KEY_HOME Wiimote.1 = KEY_PROG1 Wiimote.2 = KEY_PROG2 ...
By default, wminput reads the configuration listed in /etc/cwiid/wminput/default to get its mappings. In this file you will see:
#acc_ptr include buttons Plugin.acc.X = REL_X Plugin.acc.Y = REL_Y
Essentially, this file includes the buttons file for keybindings, and it also enables the use of the accelerometers for X and Y movements. The great thing about wminput is that all these mappings are completely configurable. If you look in /etc/cwiid/wminput, you should see a number of other example mappings you can use as inspiration. You also can store custom mappings in your home directory under ~/.cwiid/wminput. The button mappings use standard names for keys and mouse buttons that can be found in /usr/include/linux/input.h, but most of the names are pretty straightforward.
One of the first things I wanted to do with my Wiimote after it was connected was to use it as a controller for my various game system emulators. But, before I go any further, if you do use a game system emulator like nestra, fceu, snes9x or MAME, be sure you have full rights to use any ROMs you might have. Make an appointment with your lawyer for details, but essentially, to play a commercial ROM, you should own the corresponding game.
With the legal disclaimers aside, the Wiimote makes a great wireless NES (Nintendo Entertainment System) controller. All the basic buttons are there, and all that's left to do is rearrange the button mappings to work with either nestra or fceu NES emulators. Both programs use slightly different mappings, so I created files called buttons-fceu and buttons-nestra and placed them in ~/.cwiid/wminput. First, buttons-nestra:
Wiimote.A = KEY_0 Wiimote.B = KEY_1 Wiimote.Up = KEY_LEFT Wiimote.Down = KEY_RIGHT Wiimote.Left = KEY_DOWN Wiimote.Right = KEY_UP Wiimote.Minus = KEY_TAB Wiimote.Plus = KEY_ENTER Wiimote.Home = KEY_PAUSE Wiimote.1 = KEY_Z Wiimote.2 = KEY_SPACE
After I set the regular NES buttons, I had a few extra to bind, so I bound the A button to pause the emulator, the B button to set nestra to normal speed and the home button to reset the game.
The fceu emulator had completely different keybindings, so here is my buttons-fceu file:
Wiimote.A = KEY_F7 Wiimote.B = KEY_F5 Wiimote.Up = KEY_A Wiimote.Down = KEY_S Wiimote.Left = KEY_Z Wiimote.Right = KEY_W Wiimote.Minus = KEY_TAB Wiimote.Plus = KEY_ENTER Wiimote.Home = KEY_F10 Wiimote.1 = KEY_KP2 Wiimote.2 = KEY_KP3
In addition to the standard buttons, I bound the B button to save a game state, A to restore and home to reset the game.
Now, to use either of these configuration files, all I need to do is tell wminput to load these files instead:
greenfly@minimus:~/$ wminput -c ~/.cwiid/wminput/buttons-nestra Put Wiimote in discoverable mode now (press 1+2)... Ready.
Because wminput sends regular keyboard events, I don't have to do anything special to nestra or fceu.
The Wiimote worked great for NES games, but how about SNES (Super Nintendo) emulation? I actually purchased a few different SNES games for the Wii virtual console, and I also bought a Classic Controller so I would have all the standard SNES buttons. It turns out that wminput also can bind keys to the Nunchuck and Classic Controller attachments, so all I had to do for it to work with snes9x was create a new configuration file that mapped all the keys. Here is my buttons-snes9x file:
Wiimote.A = KEY_X Wiimote.B = KEY_S Wiimote.Up = KEY_LEFT Wiimote.Down = KEY_RIGHT Wiimote.Left = KEY_DOWN Wiimote.Right = KEY_UP Wiimote.Minus = KEY_TAB Wiimote.Plus = KEY_ENTER Wiimote.Home = KEY_ESC Wiimote.1 = KEY_C Wiimote.2 = KEY_D Nunchuk.C = BTN_LEFT Nunchuk.Z = BTN_RIGHT Classic.Up = KEY_UP Classic.Down = KEY_DOWN Classic.Left = KEY_LEFT Classic.Right = KEY_RIGHT Classic.Minus = KEY_SPACE Classic.Plus = KEY_ENTER Classic.Home = KEY_ESC Classic.A = KEY_D Classic.B = KEY_C Classic.X = KEY_S Classic.Y = KEY_X #Classic.ZL = #Classic.ZR = Classic.L = KEY_A Classic.R = KEY_Z
Even though I planned to use the Classic Controller, I tried to map as many of the regular Wiimote keys to buttons that made sense, so you could potentially play at least some games with the regular Wiimote as well. If you notice, I also left bindings for the special ZL and ZR keys blank, so you could bind them to extra keys.
One of the best game system emulators out there is MAME. MAME emulates classic arcade games, and there are many guides out there (including in Linux Journal itself) on how to use MAME to create your own arcade cabinet. Well, I haven't cleared away the time for that project yet, but I did want to use my Wiimote and Classic Controller attachment for MAME games. MAME has a large number of bindings (press Tab in MAME to see a list), so it was difficult to choose which to bind to the extra keys. Here is a sample buttons-xmame file I created:
Wiimote.A = KEY_P Wiimote.B = KEY_5 Wiimote.Up = KEY_LEFT Wiimote.Down = KEY_RIGHT Wiimote.Left = KEY_DOWN Wiimote.Right = KEY_UP Wiimote.Minus = KEY_2 Wiimote.Plus = KEY_1 Wiimote.Home = KEY_F3 Wiimote.1 = KEY_LEFTCTRL Wiimote.2 = KEY_LEFTALT Nunchuk.C = BTN_LEFT Nunchuk.Z = BTN_RIGHT Classic.Up = KEY_UP Classic.Down = KEY_DOWN Classic.Left = KEY_LEFT Classic.Right = KEY_RIGHT Classic.Minus = KEY_2 Classic.Plus = KEY_1 Classic.Home = KEY_F3 Classic.A = KEY_LEFTCTRL Classic.B = KEY_LEFTALT Classic.X = KEY_SPACE Classic.Y = KEY_LEFTSHIFT Classic.ZL = KEY_5 Classic.ZR = KEY_P Classic.L = KEY_Z Classic.R = KEY_X
In addition to the standard bindings you might expect, the home key resets MAME; the plus key selects single player; minus selects two players; ZL on the Classic Controller and B on the Wiimote insert a coin; and ZR on the Classic Controller and A on the Wiimote pause. These are by no means perfect bindings, so I recommend you experiment with different keys that work better for you.
The possibilities with wminput go much further than what I've presented here. There also are configuration files that use the analog joystick inputs on the Classic Controller, the IR sensors on the Wiimote and the accelerometers on the Nunchuck. Wminput isn't just a handy way to play video games on your laptop or desktop. The fact that the connection to the computer is wireless makes the Wiimote a great gaming input for a MythTV client or other computer connected to your PC. As for me, I think I'll be spending a few more days trying to beat this impossible Super Mario Brothers hack that has been floating around the Internet.
Special Magazine Offer -- Free Gift with Subscription
Receive a free digital copy of Linux Journal's System Administration Special Edition as well as instant online access to current and past issues. CLICK HERE for offer
Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.
Subscribe now!
The Latest
Newsletter
Featured Videos
Set up a secure virtual host in Apache
December 22nd, 2008 by Elliot Isaacson in
Setting up an https server in Apache is easy. This tutorial covers how to create and sign your ssl certificate as well as how to configure the web server.
Recently Popular
From the Magazine
January 2009, #177
It's a battle as old as time: good vs. evil. Fortunately, Linux and FOSS are on our side as we wage the battle against those who try to steal our secrets and invade our systems.
Checking your system's security is best done sooner rather than later. Test the locks with our article on security verification; find out how to use PAM to help secure your systems; use MinorFS and AppArmor to implement discretionary access control; learn more about Samba security in part III of our series; use Darknet to help detect bots and secure your systems; use the Yubikey to increase your site's security; and don't forget to lock the doors, because a cold boot attack could render your security useless if somebody has physical access to your computer.
But, we're not just about sowing the seeds of fear. We also show you how to use memcached in Rails, how to manage multiple servers efficiently, how to deploy applications easily with Capistrano, how to manage your videos with MythVideo, how to mix it up a bit (your audio that is), and even play a few games.
Delicious
Digg
Reddit
Newsvine
Technorati





And what about Slackware?
On December 13th, 2008 Dr Who (not verified) says:
Did anyone think of trying this on Slackware? Either 11.0 or 12.1 or Current.
Ubuntu Intrepid
On December 9th, 2008 Anonymous (not verified) says:
Works great on Ubuntu Hardy, but has anyone got it to work on Ubuntu Intrepid?
something to do with uinput version...?
Gens Control
On November 12th, 2008 schwieb (not verified) says:
I don't even have a Wii and I had to buy one of these controllers! They are totally awesome!
Though this may be sacrilegious, in addition to the NES emulators I use mine with the Sega emulator Gens. Here is my configuration!
# Wiimote Gens
Wiimote.A = KEY_F5
Wiimote.B = KEY_F5
Wiimote.Up = KEY_LEFT
Wiimote.Down = KEY_RIGHT
Wiimote.Left = KEY_DOWN
Wiimote.Right = KEY_UP
Wiimote.Minus = KEY_TAB
Wiimote.Plus = KEY_ESC
Wiimote.Home = KEY_ENTER
Wiimote.1 = KEY_A
Wiimote.2 = KEY_S
Thanks for the article.
Post new comment