Wiimote Syncing

Properly syncing Wiimotes and Wiimote-like devices (like the balance board) has long been one of the two primary unsolved issues in open source Wiimote interfaces (the other being sound, although the notes at [wiibrew http://wiibrew.org/wiki/Wiimote#Speaker_Configuration] sound like some progress has been made). Based on others' discoveries (here and here), I've got a process for syncing a Wiimote to a PC, although you've got to get your hands dirty to do it. As these pieces are cleaned up, I'll commit the relevant parts to CWiid.

The Syncing Process

  1. After pressing the red sync button in the battery compartment of the Wiimote, the controller will be discoverable and accept pairing requests.
  2. The host device pairs with the Wiimote, using the address of the host device in binary, and backwards (litte-endian).
  3. The host device connects to the Wiimote as usual, e.g. using cwiid_open.
  4. After this connection ends, pressing any button on the Wiimote will cause the controller to attempt to connect to the host device.

Outstanding Issues

There are currently four open issues with syncing:

  1. The first byte of every Bluetooth device I've seen is 0, so any code that interprets the pin as a null-terminated string will break. The conventional way to specify the pin to the Bluetooth daemon is over D-Bus, but D-Bus throws an error if you attempt to return a string containing a null. Pins can also be specified in /var/lib//bluetooth/<Host Device Bluetooth Address>/pincodes, but the Bluetooth package still needs to be patched to handle the null character.
  2. The Wiimote does not (as far as I can tell, but I'm not a Bluetooth expert) finish the pairing process correctly. However, while the pairing connection is still in limbo, the host device must initiate a standard data connection. I know of no way to robustly synchronize this sequence, so the script provided simply waits 2 seconds between the pairing attempt and the connection attempt.
  3. The Wii can somehow tell whether the power button or some other button has been pressed, and only accepts the connection in the former case. I have been unable to find a way to determine which button was pressed. The cwiid_server function, therefore, always connects.
  4. The BlueZ daemon has several plugins that handle various types of devices. The input plugin will attempt to handle incoming Wiimote connections, and must be disabled to allow CWiid to handle the connection. Unfortunately, this precludes the use of other Bluetooth input devices while using CWiid to handle incoming connections.

The Process (Overview)

  1. Patch BlueZ to read pins with null bytes, and install the patched BlueZ
  2. Add the pincode to /var/lib/<Host Device Bluetooth Address>/pincodes.
  3. Pair and connect to the Wiimote.
  4. Disconnect from the Wiimote.
  5. Run <script>.
  6. Press a button on the Wiimote.

The Process (Detail)

  1. BlueZ Installation
    1. Download BlueZ 4.60 sources.
    2. Patch the sources with the attached null_pin.patch.
    3. Install the patched BlueZ.
  2. Install CWiid from the latest git sources.
  3. Add the pincode for your wiimote to /var/lib/<Host Device Bluetooth Address>/pincodes with the attached add_pin script. Run the command
     add_pin <host address> <wiimote address> >> /var/lib/bluetooth/<host address>/pincodes
    
    The host address can be found with hcitool dev, and the wiimote address with lswm.
  4. Pair and connect to the wiimote with the attached attachment:wiimote_sync

Attachments